"子数组和的最大值问题“题解 | 豆包MarsCode AI刷题

72 阅读5分钟

子数组和的最大值问题 —— 从思路到实现

这道题考察了我们对滑动窗口技巧的理解,并需要我们灵活地处理删除元素后求子数组最大和的情况。本文将从问题分析、解题思路到代码实现逐步深入。


问题描述

小U手上有一个整数数组,他想知道如果从数组中删除任意一个元素后,能得到的长度为 k 的子数组和的最大值。你能帮小U计算出这个结果吗?
如果数组恰好为 k 个元素,那么不进行删除操作。

测试用例如下:

  • 示例 1n = 5, k = 3, nums = [2, 1, 3, -1, 4],输出 8
  • 示例 2n = 6, k = 2, nums = [-1, -1, 5, -2, 3, 4],输出 8
  • 示例 3n = 4, k = 2, nums = [-5, -3, 2, 1],输出 3

题目分析

在分析这个问题时,我们需要注意几个关键点:

  1. 特殊情况处理:当数组的长度 ( n ) 刚好等于 ( k ) 时,不需要进行任何删除操作,直接返回数组和即可。

  2. 滑动窗口的使用:我们可以使用滑动窗口技巧来动态计算长度为 ( k+1 ) 的子数组和。通过在窗口中尝试删除一个元素,可以获得长度为 ( k ) 的子数组,从而获得最大和。

  3. 多次尝试删除的逻辑:我们需要在每个滑动窗口中删除不同的位置元素,并计算删除后的子数组和,从而找到最大的和。


解题思路

为了高效地解决这个问题,我们可以按照以下步骤进行:

  1. 初始化滑动窗口:首先计算数组前 ( k+1 ) 个元素的和作为初始滑动窗口。这个窗口的长度为 ( k+1 ),比目标子数组多一个元素,以便在删除操作后获得长度为 ( k ) 的子数组。

  2. 遍历窗口并删除元素:对于初始窗口中的每一个元素,尝试删除它,计算剩余 ( k ) 长度子数组的和,更新最大和。

  3. 动态更新滑动窗口:随着窗口的滑动,减去窗口左边的一个元素并加入新的右边元素,保持窗口长度为 ( k+1 )。对新的窗口再次进行删除元素操作,更新最大和。

  4. 输出结果:最终获得所有可能的删除后的子数组和中的最大值。

通过这种方式,我们可以在 ( O(n * k) ) 的时间复杂度内高效解决问题。


代码实现

以下是完整的 Python 代码实现,附有详细注释:

def solution(n, k, nums):
    # 特殊情况:如果数组长度等于 k,直接返回数组的和
    if n == k:
        return sum(nums)

    # 初始化最大和为负无穷
    max_sum = float('-inf')
    # 计算初始滑动窗口(长度为 k+1)的和
    cur_sum = sum(nums[:k + 1])

    # 遍历窗口中的每一个元素,尝试删除并更新最大和
    for i in range(k + 1):
        max_sum = max(max_sum, cur_sum - nums[i])
    
    # 滑动窗口遍历剩余部分
    for i in range(k + 1, n):
        # 更新滑动窗口和:去掉左边元素,加上右边新元素
        cur_sum = cur_sum - nums[i - k - 1] + nums[i]
        # 在新的窗口中尝试删除每一个元素
        for j in range(i - k, i):
            max_sum = max(max_sum, cur_sum - nums[j])

    return max_sum

代码详解

  1. 初始化特殊情况:如果 ( n = k ),数组长度刚好等于子数组长度 ( k ),直接返回数组的总和。

  2. 滑动窗口初始化:计算初始的 ( k+1 ) 长度的窗口和。这个窗口和代表初始状态,我们将在后续滑动中不断更新。

  3. 删除窗口内元素并更新最大和:对于初始窗口的每一个元素,尝试删除该元素,计算删除后的子数组和,并更新最大和 max_sum

  4. 滑动窗口动态更新:当窗口向右移动时,去掉最左侧的元素,并加入新的元素来保持窗口和的更新。

  5. 删除新窗口中每个元素并更新:对于新的滑动窗口,重复删除元素的操作,记录最大和。


思考与总结

在这个解法中,滑动窗口法是核心。通过初始化 ( k+1 ) 的窗口和,每次滑动时更新窗口内容,我们可以高效地在窗口内进行删除操作。这样使得每个滑动窗口都是一个完整的子数组,我们通过删除一个元素获得长度为 ( k ) 的子数组和,从而得到了符合题目要求的最大和。


算法优化与时间复杂度分析

  1. 时间复杂度:当前算法的时间复杂度为 ( O(n * k) ),因为对于每一个滑动窗口位置都要遍历 ( k ) 个元素来尝试删除。该算法在处理一般规模的输入时效率较高,但在极大输入的情况下可能影响性能。

  2. 空间复杂度:算法的空间复杂度为 ( O(1) ),因为只需要常数的额外空间存储最大和 max_sum 以及当前窗口和 cur_sum

  3. 优化方向:若需要更高效的解决方案,可以尝试通过记录最大和的区间来减少不必要的遍历,或者通过动态规划优化此过程。


结语

本题通过删除一个元素求最大子数组和,考察了滑动窗口的应用和动态更新技巧。滑动窗口在减少时间复杂度的同时,保证了遍历的完整性和效率。在解题过程中,需要特别注意窗口内元素删除后的子数组和计算,确保逻辑严谨。