给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
输入:s = 7,nums = [2,3,1,2,4,3]
输出:2
输入:s = 4,nums = [1,4,4]
输出:1
完整思路如代码随想录所示
本章仅对其中的滑动窗口方法进行解释。
什么是滑动窗口呢?我的理解就是建立一个可以滑动的窗口,具体在于窗口的左右边界是可以移动的,窗口的大小也是不固定的。拿示例中s=7的情况进行举例。
整个数组用图表现是这样的。
首先滑动窗口的左边界停留在数组最左边不动,滑动窗口的右边界开始一格一格的向右移动,直到滑动窗口左右边界内的值之和≥ s,即≥ 7。
在这种情况下,滑动窗口内的值的和等于8大于了s,这时候就需要将滑动窗口的左边界向右移动(一格一格移动)。
移动后将滑动窗口内的和与s进行比较,如果和还是≥ s,那继续移动滑动窗口的左边界;如果和<s,那移动滑动窗口的右边界。
重复上述步骤,直到滑动窗口的右边界到达数组最后,在此过程中其实能得到所有和≥s的情况,从而得到题目要求的最小子数组。具体的关键代码分析如下:
l = len(nums)
left = 0
right = 0
min_len = float('inf')
cur_sum = 0 #当前的累加值
其中min_len = float('inf')的意义在于设定一个初始的最小值以供和后续每个和≥s的滑动窗口长度进行比较。其中float('inf')代表正无穷(ps:float('-inf')代表负无穷,其他题目中如需要比较最大值,可将负无穷作为比较的初始值)。cur_sum代表滑动窗口内值的和。
while right < l:
cur_sum += nums[right]
while cur_sum >= s: # 当前累加值大于目标值
min_len = min(min_len, right - left + 1)
cur_sum -= nums[left]
left += 1
right += 1
前两行代码的意思即上文中提到的“滑动窗口的右边界开始一格一格的向右移动”,不停的加入新的值,更新得到的和。
当滑动窗口内的和cur_sum≥s时,代表发现了一个子数组和≥s的情况,将该子数组长度于之前的min_len进行对比,将更小的值赋给min_len。
对比结束后,滑动窗口左边界向右移动一格,同时cur_sum中减去该格的值。如果cur_sum依旧≥s,则继续进行循环while cur_sum >= s:;如果不是,则回到循环while right < l:,同时滑动窗口的右边界再向右移动一格,继续循环,不停的更新min_len,直到所有循环结束。
return min_len if min_len != float('inf') else 0
理论上,如果存在和≥s的子数组的话,在不停的更新min_len后会得到最小的子数组长度,但还需要考虑滑动窗口右边界一直向右移动直到移动到最后,其和都小于s的情况,该情况下min_len并未进行更新,依旧是正无穷float('inf'),因此在最后的return中还需设置一个if判断,上述代码只是将该判断进行了简化。
标签:窗口,cur,min,最小,len,数组,滑动,长度 From: https://blog.csdn.net/plutomty/article/details/140502388