大家好呀,我是帅蛋。
今天解决长度最小的子数组,滑动窗口解决的经典题目,之前做过一道用队列求滑动窗口最大值。
滑动窗口呢,一般就用在数组或者字符串上,我们先从字面上来认识一下滑动窗口:
- 滑动:窗口可以按照一定的方向移动。
- 窗口:窗口大小可以固定,也可以不固定,此时可以向外或者向内,扩容或者缩小窗口直至满足条件。
了解了这些,下面开始直接肝题。
LeetCode 209:长度最小的子数组
题意
给定含有 n 个正整数的数组和一个正整数 target:
找出该数组中满足其和 ≥ target 的长度最小的连续子数组,并返回其长度,若不存在,返回 0。
示例
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
提示
- 1 <= target <= 10^9
- 1 <= len(nums) <= 10^5
- 1 <= nums[i] <= 10^5
题目解析
中等难度题,但是知道了思路,代码难度几乎没有,属于中等难度中的菜鸡。
通常最开始想到的最简单的方法肯定是暴力查找。
遍历数组 nums,每次将一个下标的元素作为子数组的开始,接下来从下标 i 开始向后遍历,找到最小下标 j,使得从 nums[i] 到 nums[j] 的和 >= target,更新子数组的最小长度。
这种方式使用双重 for 循环,时间复杂度为 O(n²),鉴于 nums 的最大长度为 10^5,显然不是好办法。
不过我无聊试了一下,在 LeetCode 上暴力法是可以 AC 的,不过执行时间看的我直嘬牙花子。
而这道题比较经典的解法就是滑动窗口。
滑动窗口,看起来名字挺高大上,有点唬人,但是禁不住细看。
在文章开头我大概介绍了滑动窗口是啥,这本质上和解决【LeetCode 29 有序数组的平方】里用的 left 和 right 双指针没啥区别,只不过动的更自如,left 和 right 之间的间隔可以忽大忽小。
知道了这些,那解题步骤就很明确了:
- 使用左右指针 left 和 right,left 和 right 之间的长度即为滑动窗口的大小(即连续数组的大小)。
- 如果滑动窗口内的值 sum >= target,维护连续数组最短长度,left 向右移动,缩小滑动窗口。
- 如果滑动窗口内的值 sum < target,则 right 向有移动&