题目
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0。
解题方法1:暴力双循环解法(不推荐)
这题有一种简单粗暴的解法,双循环遍历数组,最外层遍历的值 i 为数组的开始下标,内层循环遍历的下标 j ,数组下标从 i 到 j 的元素和满足不小于 target 时,计算每一次这样遍历时从 i 到 j 的长度,题目需要我们返回小的长度。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int res=nums.length + 1;
// 暴力循环
for(int i = 0; i < nums.length; i++){
int sum = 0; //从i到j的和
for(int j = i; j < nums.length; j++){ //从i到j有j-i+1个数
sum += nums[j];
if(sum >= target){
int sss=j - i + 1;
res = res < sss ? res : sss;
break;
}
}
}
return res == nums.length + 1 ? 0 : res; //如果res无变化,说明整个数组不存在满足连续和>=target的
}
}
解题方法2:滑动窗口(双指针)
滑动窗口实际也是双指针的一种。只不过解题方法像一个长度可变,并且向右滑动的窗口。
首先理清几个关键概念:
1,滑动窗口内就是所有元素和满足不小于题目所给 target 的长度最小的连续数组元素。
2,滑动窗口的始末位置,当当前滑动窗口内的值不小于 target 时,滑动窗口的大小应该缩小,起始位置需要向后移动:当滑动窗口口内的值小于 target 时,滑动窗口的大小应该要变大,即末位置应该向后移动。这样一直移动到遍历完整个数组。
3,在每一次遍历过程中,记录当滑动窗口内的值刚好不小于 target 时的滑动窗口长度,题目结果需要我们返回求得得最小长度。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int res = nums.length + 1; //最大长度不可能超过这个长度
//滑动窗口(快慢指针)
int slowIndex = 0;
int fastIndex = 0;
int sum = 0;
//快指针遍历,快慢指针一起定位
while(fastIndex < nums.length){
sum += nums[fastIndex]; //快指针向右移动
while(sum >= target){ //只要快慢指针对应下表之间数组的和不小于target
res = res < (fastIndex - slowIndex + 1) ? res : (fastIndex - slowIndex + 1);
sum -= nums[slowIndex]; //慢指针向右移动
slowIndex++;
}
fastIndex++; //当不满足上面循环条件,即和不够,则快指针向右移动
}
return res == nums.length + 1 ? 0 : res;
}
}