题目描述
小U手上有一个整数数组,他想知道如果从数组中删除任意一个元素后,能得到的长度为 k 的子数组和的最大值。你能帮小U计算出这个结果吗?
如果数组恰好为 k 个元素,那么不进行删除操作。
样例1:
输入:
n = 5,k = 3,nums = [2, 1, 3, -1, 4]
输出:8
题目解析
这个题目中我们要注意几个点:
- 子数组和 --> 数组中连续的数据的和,可以用滑动窗口求解
- 在这其中会删除一个数得到长度为k的子数组和的最大值 --> 滑动窗口
- 由题意中的能得到可知,数组的长度肯定是大于等于k的。而且如果n恰好为K则子数组就是原数组
根据条件2,我们可以分为两种情况,一种是数组长度大小刚好等于k,即n=k,一种是数组长度大于K即n>k
- 当n=k时,子数组就是这个数组,子数组和的最大值就是数组中所有元素的和,那么我们进行累加就可以了。
if n ==k :
for num in nums:
s +=num
ans = s
-
当n不等于k时,给出的这个整数数组就是长度大于k的情况下,我们要对该数组进行操作,对其求子数组的最大值。
那使用滑动窗口求最大值,也就是求滑动窗口中的最大值。如何求滑动窗口呢?
我们可以定义一个双指针,不过这次的双指针是头尾指针,而头尾指针中包含K个数据,看上去就像一个“窗口”,而我们根据条件2的要求,要求窗口内的数和的最大值。
具体步骤为:
- 定义一个s变量求滑动窗口中数的和,一个ans记录窗口中长度为k的数字和的最大值(初始化为很小的值)
s,start = 0,0
ans= -float("inf")
-
定义首尾指针,一个指向数组索引为0的位置的首指针start,一个尾指针end,但是这个end放在for循环中,每一次循环加1,指向下一个数。
-
end在for循环中遍历每个元素,当end-start+1(窗口的长度)大于k的时候(此时窗口长度应为k+1),我们再遍历窗口中的值,然后删除其中任意一个数(每个数都删除一遍),然后比较s(当前滑动窗口的总值)和ans(历史窗口最大值)
-
然后再将删除的数加回来,此时我们已经完成了一遍长度为k的窗口内的最大值查找,(因为我们仍要保持s是窗口中的所有值的和,所以我们要将删除的数加回来)
-
移除窗口起始位置的元素,即将
nums[start]从s中减去,并将start向后移动一位,因为我们的窗口要向右移动一位了,同时我们要保证窗口值为k+1,因为在for循环中,end稍后会+1 -
然后start+1,窗口滑动(此时end+1,start也+1,相当于窗口向后滑动了一次),然后继续查找窗口内的最大值,直到遍历完毕,也就是直到
end==n-1为止
for end in range(len(nums)):
s +=nums[end]
if end-start+1==k+1:
for i in range(start,end+1):
s-=nums[i]
ans = max(ans,s)
s+=nums[i]
s -= nums[start]
start +=1
完整代码
ef solution(n, k, nums):
# Edit your code here
s,start = 0,0
ans= -float("inf")
if n ==k :
for num in nums:
s +=num
ans = s
else:
for end in range(len(nums)):
s +=nums[end]
if end-start+1==k+1:
for i in range(start,end+1):
s-=nums[i]
ans = max(ans,s)
s+=nums[i]
s -= nums[start]
start +=1
print("ans:",ans)
return ans