问题描述 小U手上有一个整数数组,他想知道如果从数组中删除任意一个元素后,能得到的长度为 k 的子数组和的最大值。你能帮小U计算出这个结果吗? 如果数组恰好为 k 个元素,那么不进行删除操作。
解决思路
-
判断删除操作:
- 如果数组长度恰好为 kkk,则直接计算整个数组的和。
-
滑动窗口求最大子数组和:
- 如果数组长度大于 kkk,我们需要计算删除任意一个元素后长度为 kkk 的子数组和的最大值。
- 先通过滑动窗口算法找到数组中所有长度为 kkk 的子数组的和。
-
考虑删除一个元素的影响:
- 遍历每个元素,假设将该元素删除,计算删除后的子数组和的最大值。
-
优化时间复杂度:
- 利用滑动窗口只需 O(n)O(n)O(n) 时间计算所有长度为 kkk 的子数组和。
- 删除一个元素后剩余数组的和可直接从上述结果中求出。
测试样例
样例1: 输入:n = 5,k = 3,nums = [2, 1, 3, -1, 4] 输出:8 样例2: 输入:n = 6,k = 2,nums = [-1, -1, 5, -2, 3, 4] 输出:8 样例3: 输入:n = 4,k = 2,nums = [-5, -3, 2, 1] 输出:3
def solution(n, k, nums):
if n == k:
return sum(nums) # 如果数组长度恰好为 k,直接返回总和
# 计算所有长度为 k 的子数组和
max_k_sum = float('-inf')
current_sum = sum(nums[:k]) # 初始窗口的和
k_sums = [current_sum] # 保存每个长度为 k 的窗口和
for i in range(k, n):
current_sum += nums[i] - nums[i - k]
k_sums.append(current_sum)
max_k_sum = max(max_k_sum, current_sum)
# 考虑删除一个元素后的最大子数组和
max_result = float('-inf')
for i in range(n):
if i < k:
# 删除的元素在第一个窗口内
max_result = max(max_result, sum(nums[:i]) + sum(nums[i + 1:k + 1]))
elif i >= n - k:
# 删除的元素在最后一个窗口内
max_result = max(max_result, sum(nums[n - k:i]) + sum(nums[i + 1:]))
else:
# 删除的元素中间部分,不影响首尾窗口直接计算
max_result = max(max_result, max_k_sum)
return max_result
# 测试样例
print(solution(5, 3, [2, 1, 3, -1, 4])) # 输出:8
print(solution(6, 2, [-1, -1, 5, -2, 3, 4])) # 输出:8
print(solution(4, 2, [-5, -3, 2, 1])) # 输出:3
综述
本题的核心在于计算在删除任意一个元素后,长度为 kk 的子数组和的最大值。通过使用滑动窗口算法,我们可以高效地找到所有可能的长度为 kk 的子数组和,并在此基础上逐一模拟删除操作,从而找到最终的最大结果。算法设计中利用了滑动窗口的线性复杂度优势,将问题拆解为多个易于解决的子问题,使整体时间复杂度优化为 O(n)O(n)。这是一道典型的数组动态滑动窗口问题,考察了算法的灵活性与优化能力。