青训营X豆包MarsCode 技术训练营之子数组和的最大值问题 | 豆包MarsCode AI 刷题

40 阅读4分钟

问题描述

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


测试样例

样例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

问题的求解思路

1. 特殊情况的处理

在正式求解之前,先考虑一些特殊情况:

  • 数组长度等于 k:如果 n=k,这意味着我们无法删除任何元素,直接返回数组的总和即可。这个特例可以在代码中单独处理。
  • 数组长度大于 k:这种情况下需要通过滑动窗口法计算子数组和的最大值,同时考虑删除元素的影响。

2. 滑动窗口的基本原理

滑动窗口是一种高效计算固定大小子数组和的方法:

  • 在长度为 k的窗口中,记录窗口内的元素和。
  • 窗口从数组的起点向终点滑动,每次移入一个新元素,同时移出窗口中最左边的元素。
  • 在滑动过程中,更新子数组和的最大值。

滑动窗口的时间复杂度为 O(n),远优于暴力求解所有子数组和的 O(nk)。

3. 删除元素的模拟

要计算删除一个元素后形成的最大子数组和,可以通过以下步骤完成:

  1. 遍历数组的每个元素,假设当前删除的是第 i 个元素。
  2. 生成一个新的数组,即原数组去掉第 i个元素。
  3. 对新的数组应用滑动窗口法,计算长度为 k 的子数组和的最大值。
  4. 将上述结果与全局最大值比较并更新。

通过这种模拟,我们可以验证删除每个元素后的最优情况。

以下是 Python 代码实现,包含详细注释:

python
复制代码
def max_k_sum_after_removal(n, k, nums):
    # 特殊情况:如果数组长度正好等于 k,则无需删除元素
    if n == k:
        return sum(nums)

    # 定义一个函数,计算数组中长度为 k 的子数组的最大和
    def max_k_sum(arr):
        window_sum = sum(arr[:k])  # 初始窗口和
        max_sum = window_sum
        for i in range(k, len(arr)):
            # 窗口滑动:加入一个新元素,移出一个旧元素
            window_sum += arr[i] - arr[i - k]
            max_sum = max(max_sum, window_sum)
        return max_sum

    # 遍历每个元素,模拟删除
    max_result = float('-inf')  # 初始化最大值
    for i in range(n):
        # 删除第 i 个元素后的新数组
        remaining = nums[:i] + nums[i+1:]
        # 计算剩余数组的最大子数组和
        max_result = max(max_result, max_k_sum(remaining))

    return max_result

算法分析

1. 时间复杂度

  1. 滑动窗口计算

    • 每次计算长度为 k 的子数组和需要 O(n)。
    • 删除每个元素后,需要重新计算一次,总共 n 次。

    总时间复杂度:O(n^2)。

  2. 空间复杂度

    • 模拟删除元素时会创建新数组,空间复杂度为 O(n)。

2. 优化方向

  • 对于每次删除后重新计算子数组最大和,可以尝试动态规划(动态更新子数组和)进一步优化。
  • 可以避免显式地复制数组,而通过直接跳过第 i 个元素实现更高效的滑动窗口。

测试样例与结果分析

样例 1

输入:n=5,k=3,nums=[2,1,3,−1,4]

  1. 删除第 1 个元素后,数组为 [1,3,−1,4],最大子数组和为 8。
  2. 删除第 2 个元素后,数组为 [2,3,−1,4],最大子数组和为 7。
  3. 删除第 3 个元素后,数组为 [2,1,−1,4],最大子数组和为 5。
  4. 删除第 4 个元素后,数组为 [2,1,3,4],最大子数组和为 9。

输出:8

样例 2

输入:n=6,k=2,nums=[−1,−1,5,−2,3,4]

  1. 删除第 1 个元素后,数组为 [−1,5,−2,3,4],最大子数组和为 8。
  2. 删除第 2 个元素后,数组为 [−1,5,−2,3,4],最大子数组和为 8。

输出:8

在这篇博客中,我们探讨了如何求解一个经典的数组问题:从一个整数数组中删除一个元素后,计算能够得到的长度为 k 的子数组和的最大值。我们通过滑动窗口技术有效地计算了子数组的和,同时模拟了删除元素对结果的影响,最终找到了问题的解法。