LeetCode209.长度最小的子数组
https://leetcode-cn.com/problems/minimum-size-subarray-sum
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
进阶:
如果你已经完成了 O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。
O(n)解法 :滑动窗口
定义两个指针 l , r 分别表示窗口的左右两边,其初始位置分别为 0 和 -1 。设置一个变量 sum 表示窗口中数值的和(l~r之间的和)。
先判断sum与 s 的关系:
如果 sum < s ,意味着需要增加窗口长度来提高sum值使其靠近s,此时需要 r++;
如果 sum >= s ,意味着需要减少窗口长度来降低sum值使其靠近s,此时需要 l++;
再判断窗口中的和( sum )是否符合题意,需要进行一次判断 sum >= s。若符合,则将此次窗口的长度与上一次长度比较取出较小的值。
直到遍历完整个数组。
若遍历完整个数组之后仍未发现符合题意的窗口,返回0。
时间复杂度:O(n),其中 n 是数组的长度。指针 l 和 r 最多各移动 n 次。
空间复杂度:O(1)。
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int l = 0, r = -1;
int minLen = nums.size() + 1;
int sum = 0;
while(l < nums.size()) {
if( r+1 < nums.size() && sum < s ) // 限制r的范围,防止其出去
sum += nums[++r];
else
sum -= nums[l++];
if(sum >= s) //此处的sum >= s和上面的else不一样
minLen = min( minLen, r-l+1 );
}
if(minLen == nums.size() + 1) //遍历完了还是原来的值,意味着不符合题意
return 0;
return minLen;
}
};
O(n log n) 解法:前缀和 + 二分查找
看官方题解吧:说得比我清楚: https://leetcode-cn.com/problems/minimum-size-subarray-sum/solution/chang-du-zui-xiao-de-zi-shu-zu-by-leetcode-solutio/