刷题笔记 | 豆包MarsCode AI刷题

77 阅读3分钟

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


解决思路

  1. 判断删除操作

    • 如果数组长度恰好为 kkk,则直接计算整个数组的和。
  2. 滑动窗口求最大子数组和

    • 如果数组长度大于 kkk,我们需要计算删除任意一个元素后长度为 kkk 的子数组和的最大值。
    • 先通过滑动窗口算法找到数组中所有长度为 kkk 的子数组的和。
  3. 考虑删除一个元素的影响

    • 遍历每个元素,假设将该元素删除,计算删除后的子数组和的最大值。
  4. 优化时间复杂度

    • 利用滑动窗口只需 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)。这是一道典型的数组动态滑动窗口问题,考察了算法的灵活性与优化能力。