1.题目描述
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
2.代码
//滑动窗口
// 2, 7, 1, 2, 1, 3
public static int minSubArrayLen1(int target, int[] nums) {
int n = nums.length;
if (n == 0) {
return 0;
}
int minL = Integer.MAX_VALUE;
int L = 0, R = 0; //滑动窗口的左右边界
int sum = 0;
while ( R < n ) {
sum += nums[R];
while ( sum >= target ) {
minL = Math.min(minL, R - L + 1);
sum -= nums[L];
L++;
}
R++;
}
return minL == Integer.MIN_VALUE ? 0 : minL;
}
3.相关论述
核心思想
" 涉及连续子数组的问题,我们通常有两种思路:一是滑动窗口、二是前缀和。"
本题滑动窗口的核心思想是:遍历一次数组,来找到以每个元素为首的连续子数组中最小的子数组长。
什么时候结束程序的循环?
窗口的左边界在sum值大于等于target值时,才进行右移。但是这其中存在一个边界问题:什么时候结束外循环。
我们不妨这么想:右边界始终是比左边界更早到达数组的末尾(下标 = n-1),因此我们以窗口的右边界跳出数组边界作为结束外循环的条件。但这时候,我们又会想窗口右边界到达数组末尾(此时还没有跳出数组),如果窗口左边界并没有遍历到数组末尾,我们怎么找到在这之后的每次窗口中存在的满足大于等于target的子数组呢?。此时,剩下的子数组是左边界到数组末尾(下标 = n-1)的元素组成的,左边界是从左往右移动的,由于数组元素都是正整数,只要有一次窗口内的sum值小于target,我们就没必要在继续移动左边界了,直接跳出内循环,让最后的右边界自增,最后结束外循环。