求解删除一个元素后长度为k的子数组和的最大值 | 豆包MarsCode AI刷题

77 阅读2分钟

笔记:求解删除一个元素后长度为k的子数组和的最大值

问题描述

给定一个整数数组,要求找到删除任意一个元素后,能得到的长度为k的子数组和的最大值。如果数组恰好为k个元素,则不进行删除操作。

解题思路

  1. 边界条件检查

    • 如果k大于数组长度n,则无法找到长度为k的子数组,返回None。
  2. 初始化

    • 计算第一个长度为k的子数组的和,存储在current_sum中。
    • 初始化结果rescurrent_sum
    • 使用双端队列min_deque来维护当前窗口的最小值索引,确保队列中的索引对应的值是单调递增的。
  3. 滑动窗口遍历

    • 从索引k开始,向右遍历数组。

    • 在每一步中:

      • 更新结果res为当前窗口的和加上新的元素,减去当前窗口的最小值(通过min_deque[0]获取)。
      • 移动窗口,更新current_sum,通过添加新元素和去掉旧元素来调整和。
      • 更新min_deque,确保它只包含当前窗口的有效索引,并且保持单调递增。这包括移除超出窗口范围的索引和比新元素大的索引。
  4. 返回结果

    • 最终返回res,即所有可能的长度为k的子数组(删除一个元素后)的最大和。

代码实现

python复制代码
	from collections import deque

	 

	def solution(n, k, nums):

	    if k > n:

	        return None

	    

	    # 计算第一个窗口的和

	    current_sum = sum(nums[:k])

	    res = current_sum

	    

	    # 创建一个双端队列来维护当前窗口的最小值索引

	    min_deque = deque()

	    

	    # 初始化双端队列

	    for i in range(k):

	        while min_deque and nums[min_deque[-1]] >= nums[i]:

	            min_deque.pop()

	        min_deque.append(i)

	    

	    # 滑动窗口遍历

	    for i in range(k, n):

	        # 更新结果

	        res = max(res, current_sum + nums[i] - nums[min_deque[0]])

	        

	        # 移动窗口

	        current_sum += nums[i] - nums[i - k]

	        

	        # 更新双端队列

	        while min_deque and min_deque[0] <= i - k:

	            min_deque.popleft()

	        

	        while min_deque and nums[min_deque[-1]] >= nums[i]:

	            min_deque.pop()

	        

	        min_deque.append(i)

	    

	    # 返回结果

	    return res

示例

  • 输入:n = 5, k = 3, nums = [1, 2, 3, 4, 5]
  • 输出:9(删除1后,子数组[2, 3, 4]的和最大)

注意事项

  • 算法的时间复杂度为O(n),其中n是数组的长度。
  • 双端队列min_deque用于高效地找到当前窗口的最小值,从而避免了对每个窗口都重新计算最小值的开销。
  • 如果数组恰好为k个元素,则不进行删除操作,直接返回当前窗口的和作为结果。但由于前面的逻辑已经处理了这个情况(因为没有额外的删除操作),所以代码中没有显式检查数组长度是否等于k。