伴学笔记:如何求解删除一个元素后的最大子数组和?
问题描述:
小U手中有一个整数数组,他想知道在删除任意一个元素后,能得到的长度为 k 的子数组和的最大值。若数组正好是 k 个元素,且不能删除任何元素。我们需要编写程序来求解这个问题。
思路分析 🧠
1. 问题分析:
-
如果数组长度
n和子数组长度k相等,那就直接返回数组的和,因为不能删除任何元素。 -
否则,我们需要:
- 计算数组的所有长度为
k的子数组的和。 - 考虑删除每个元素后,如何调整子数组的和。
关键的技巧是 滑动窗口 技术,用于高效计算长度为
k的子数组和。 - 计算数组的所有长度为
2. 滑动窗口:
滑动窗口的核心思想是:计算一个子数组的和后,向右滑动窗口时,只需要将左边的元素移除,右边的元素加入。通过这种方式,我们可以避免每次都重新计算子数组和,从而提高效率。
3. 步骤:
- 步骤1: 若
n == k,直接返回数组的和。 - 步骤2: 若
n > k,遍历数组中的每个元素,尝试删除它,然后通过滑动窗口计算删除后的子数组和的最大值。
代码讲解 📜
def solution(n, k, nums):
# 如果数组长度等于k,不需要删除元素
if n == k:
return sum(nums)
# 滑动窗口求和的辅助函数
def max_k_subarray_sum(arr, k):
# 初始化滑动窗口
current_sum = sum(arr[:k])
max_sum = current_sum
# 使用滑动窗口方法更新窗口和
for i in range(k, len(arr)):
current_sum += arr[i] - arr[i - k] # 更新窗口和
max_sum = max(max_sum, current_sum) # 更新最大和
return max_sum
max_result = float('-inf') # 用于记录最终的最大值
# 遍历删除每个元素
for i in range(n):
# 删除第 i 个元素,得到新数组
new_nums = nums[:i] + nums[i+1:]
# 计算删除后的最大子数组和
max_sum = max_k_subarray_sum(new_nums, k)
# 更新最大和
max_result = max(max_result, max_sum)
return max_result # 返回最终的结果
if __name__ == "__main__":
# 测试用例
print(solution(5, 3, [2, 1, 3, -1, 4])) # 输出:8
代码细节解析 🔍
-
max_k_subarray_sum函数:- 这个函数用于计算长度为
k的子数组的最大和。 - 初始时,计算前
k个元素的和current_sum。 - 然后通过滑动窗口,逐个移动窗口右端,每次更新窗口和
current_sum,并更新最大和max_sum。
- 这个函数用于计算长度为
-
删除元素后的处理:
- 使用一个
for循环,遍历数组中的每个元素。 - 对每个元素,删除它并创建一个新的数组
new_nums,然后计算new_nums中长度为k的子数组的最大和。
- 使用一个
-
全局最大值更新:
- 每次计算删除后的子数组和后,更新
max_result变量,最终返回最优解。
- 每次计算删除后的子数组和后,更新
测试样例分析 🔧
样例 1:
输入:
n = 5
k = 3
nums = [2, 1, 3, -1, 4]
执行步骤:
-
不删除元素时,长度为
k的子数组最大和为2 + 1 + 3 = 6。 -
删除任意一个元素,重新计算最大子数组和。
- 删除
2后,子数组为[1, 3, -1],和为3。 - 删除
1后,子数组为[2, 3, -1],和为4。 - 删除
3后,子数组为[2, 1, -1],和为2。 - 删除
-1后,子数组为[2, 1, 4],和为7。
- 删除
-
返回最终结果
8(删除-1后,最大和为 8)。
样例 2:
输入:
n = 6
k = 2
nums = [-1, -1, 5, -2, 3, 4]
执行步骤:
- 不删除元素时,长度为
k的子数组最大和为5 + (-2) = 3。 - 删除任意一个元素,重新计算最大子数组和。
- 返回最终结果
8(删除-1后,最大和为 8)。
样例 3:
输入:
n = 4
k = 2
nums = [-5, -3, 2, 1]
执行步骤:
- 不删除元素时,长度为
k的子数组最大和为-3 + 2 = -1。 - 删除任意一个元素,重新计算最大子数组和。
- 返回最终结果
3(删除-5后,最大和为 3)。
总结 🌟
通过使用 滑动窗口 和 遍历删除元素 的方法,我们可以高效地计算删除一个元素后,得到的最大子数组和。此方法的时间复杂度为 O(n*k),其中 n 为数组长度,k 为子数组长度。
希望这篇笔记帮助你理解了如何解决这个问题!🌸