妙用列表前缀和,解 leetcode 2256 题
2023-12-14 14:54:47
引言
Leetcode 2256 题**《最小平均差》** 是一道难度为 Medium 的题目,考察的是对列表前缀和 的理解及其应用。
题目如下:
给定一个整数数组 nums
,请你找出 两个 子数组 nums[i], nums[i+1], ..., nums[j]
和 nums[k], nums[k+1], ..., nums[l]
,使得:
i <= k <= j <= l
- 子数组
nums[i], nums[i+1], ..., nums[j]
和nums[k], nums[k+1], ..., nums[l]
的长度相同,且 不小于2
- 子数组
nums[i], nums[i+1], ..., nums[j]
的平均值和子数组nums[k], nums[k+1], ..., nums[l]
的平均值的绝对差 最小
请你返回 i
和 k
的最小可能和。
示例 1:
输入:nums = [2,5,3,9,5,3]
输出:3
解释:我们将数组分成下面两个子数组:
- nums[1] = 5
- nums[4] = 5
这两个子数组的平均值都是 5,所以绝对差为 0,是可能的最小绝对差。
示例 2:
输入:nums = [6,4,6,3,1]
输出:7
解释:我们将数组分成下面两个子数组:
- nums[0] = 6
- nums[2] = 6
这两个子数组的平均值都是 6,所以绝对差为 0,是可能的最小绝对差。
提示:
2 <= nums.length <= 10^5
1 <= nums[i] <= 10^4
解题思路
这道题的解题思路相对简单,主要步骤如下:
-
计算出数组
nums
的前缀和prefix_sum
。 -
遍历数组
nums
,枚举子数组nums[i], nums[i+1], ..., nums[j]
的长度,对于每个长度,计算出子数组nums[i], nums[i+1], ..., nums[j]
的平均值。 -
同时,计算出子数组
nums[k], nums[k+1], ..., nums[l]
的平均值,其中k
和l
分别是i
和j
的最大值和最小值。 -
计算子数组
nums[i], nums[i+1], ..., nums[j]
和nums[k], nums[k+1], ..., nums[l]
的平均值的绝对差 。 -
将绝对差的最小值及其对应的
i
和k
的值记录下来。 -
最终返回
i
和k
的最小可能和。
代码实现
以下是用 Python 实现的完整代码:
def minimumAverageDifference(nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
prefix_sum = [0] * n
prefix_sum[0] = nums[0]
for i in range(1, n):
prefix_sum[i] = prefix_sum[i-1] + nums[i]
min_diff = float('inf')
min_i = 0
min_k = 0
for i in range(1, n-1):
for j in range(i+1, n):
avg1 = (prefix_sum[j] - prefix_sum[i-1]) / (j - i + 1)
k = j + 1
l = n - 1
while k <= l:
mid = (k + l) // 2
avg2 = (prefix_sum[mid] - prefix_sum[j]) / (mid - j + 1)
if abs(avg1 - avg2) < min_diff:
min_diff = abs(avg1 - avg2)
min_i = i
min_k = k
if avg2 > avg1:
l = mid - 1
else:
k = mid + 1
return min_i + min_k
复杂度分析
-
时间复杂度:O(n^3),其中
n
是数组nums
的长度。 -
空间复杂度:O(n),用于存储前缀和数组
prefix_sum
。
结语
本题考察了对列表前缀和的理解及其应用,解题思路相对简单,主要步骤是枚举子数组的长度,并计算每个子数组的平均值,最后比较平均值的绝对差。代码实现也不复杂,主要注意边界条件和细节处理。