数组——2.长度最小的子数组

力扣题目链接

给定一个含有 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判断,上述代码只是将该判断进行了简化。

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值