力扣——209. 长度最小的子数组 - 力扣(LeetCode)
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
- 输入:s = 7, nums = [2,3,1,2,4,3]
- 输出:2
- 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
提示:
- 1 <= target <= 10^9
- 1 <= nums.length <= 10^5
- 1 <= nums[i] <= 10^5
(1)思路:
第一种:就是暴力法。两次循环遍历找到长度最小的子数组。时间复杂度O(n^2)。(这种方法已经不适用了)
第二种:滑动窗口法。其本质上还是双指针。两指针之间可以看做是一个窗口,随着指针的变化,窗口不断滑动。所以叫滑动窗口。
其核心思想是:用两个指针在一个循环中完成两个循环的任务。时间复杂度O(n)。
(2)算法流程
1.定义两个变量 start和end,作为双指针。定义变量sum存储两指针之间的窗口值之和、minlength存储满足要求的最小数组长度。
2.确定终止条件为end==nums.size();
3.进入循环,计算start与end之间的窗口值sum。
4.如果sum<target,end加1,更新sum的值。如果sum>=target。将长度进行大小比较将更小的长度存储到minlength中。更新sum的值,start加1,。
5.不断循环直到end==nums.size(),结束循环。
6.返回minlength。(这里有一种特殊情况,就是整个数组和都小于target时要返回0,所以需要判断minlength的值是否改变了,使用一个三目运算符)。
代码实现:
int minSubArrayLen(int target, vector<int>& nums) {
int start = 0;
int end = 0;
int sum = nums[start];
int minlength =INT_MAX;
while(1)
{
if(sum<target)
{
end++;
if(end==nums.size()) break;
sum+=nums[end];
}
else
{
int length= end-start+1;
minlength = min(minlength,length);
sum-=nums[start];
start++;
}
}
return minlength==INT_MAX?0:minlength;
}