给定一个含有?n
?个正整数的数组和一个正整数?target
?。
找出该数组中满足其总和大于等于?target
?的长度最小的?连续子数组?[numsl, numsl+1, ..., numsr-1, numsr]
?,并返回其长度。如果不存在符合条件的子数组,返回?0
?。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组?[4,3]
?是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4]
输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
提示:
1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105
? ? ? ? 有题意可知,我们需要返回的是总和符合目标值的长度最小的子数组,由于子数组只能是原数组的一个连续子区间,而连续区间就是滑动窗口的典型前提,因此就可以想到用滑动窗口算法解决。
? ? ? ? 首先我们可以循环检索每个元素依次,若有值与target相同的元素,即直接返回1,因为不会再有比1再小的数组长度。
图示(参考示例 1数据):
? ? ? ? ?若没有长度为1的返回值那么咱们就开始进入正题:
? ? ? ? ? ? ? ? 设定两个指针:指针l(代表左指针)? ? ? ? 指针r(代表右指针)
? ? ? ? ? ? ? ? 当两指针之间的数之和小于target时? ? ? ? 指针r++????????
? ? ? ? ? ? ? ? 当和大于或等于target时? ? ? ? 与之前记录的比较,长度小,则保留? ? ? ? 指针l++
? ? ? ? ? ? ? ? 如此就能找出所有和等于target的可能并且可以计算出和为target的最小子数组长度
说着比较抽象,那就上图!(参考示例 1数据):
第一、二步:
? ? ? ? res记录两指针之间的值,res值小于target,指针r右移
?第三、四步:
? ? ? ? res值大于target,与最小长度比较,小则替换,指针l右移
????????
第五、六步:?
? ? ? ? 若res值等于target,与最小长度比较,小则替换
后续步骤:
?
class Solution {
public int minSubArrayLen(int target, int[] nums) {
//设定指针l和指针r
int l=0,r=1;
//设定窗口最小长度,初始值要大于窗口最大长度
int min=100001;
//循环检索所有元素,等于target则返回1
for(int x=0;x<nums.length;x++){
if(nums[x]>=target) return 1;
}
if(nums.length==1) return 0;
int res=nums[0]+nums[1];
//开始窗口滑动操作
while(r<nums.length){
//小于target,指针r++
if(res<target){
r++;
if(r>=nums.length) break;
res+=nums[r];
}
//大于等于target,指针l++
else if(res>=target){
//记录最小长度
min=Math.min(min,r-l+1);
res-=nums[l];
l++;
}
}
//若min值没变,则说明没有符合条件的情况
if(min!=100001) return min;
return 0;
}
}