给定一个含有 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
进阶:
- 如果你已经实现
O(n)
时间复杂度的解法, 请尝试设计一个O(n log(n))
时间复杂度的解法。
滑动窗口法:
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
只用一个for循环,这个循环的索引,一定是表示 滑动窗口的终止位置
当窗口内元素和大于等于目标值时,就要向前移动
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int slow =0;//窗口起始位置
int sum=0;//窗口内元素和
int minSize=Integer.MAX_VALUE;//最小长度
for(int j=0;j<nums.length;j++){
sum+=nums[j]; //先起始位置不动,移动窗口结束位置,计算和
while(sum>=target){//当和大于等于目标值时,结束位置不动,移动起始位置,窗口缩小
minSize = Math.min(j-slow+1,minSize);//重新计算最小长度,注意长度计算是结束位置-起始位置+1
sum-=nums[slow];//先把出窗口的元素从和中减去
slow++;//起始位置指针向前移动
}
}
return minSize==Integer.MAX_VALUE?0:minSize;//防止出现nums.length=0情况
}
}
为什么内层不用if判断而要用while
这种场景下,窗口和仍然是大于等于目标值的,如果不用while,那么就开始移动结束位置元素,起始位置不动了,实际上窗口内元素只有在小于目标值时,才能移动结束位置,否则需要移动开始位置