209. 长度最小的子数组
滑动窗口法
class Solution {
public int minSubArrayLen(int target, int[] nums) {
/**
* 滑动窗口
* 两个指针同向移动,如果当前窗口内的元素和大于target就记录长度,然后left指针右移缩小查找范围
* 如果小于target,right指针右移扩大查找范围
*/
int left = 0;
int right = 0;
int min = nums.length;
boolean flag = true;
int sum = nums[0];
while (left <= right){
if (sum >= target){
/**
* flag标志位用来判断min到底有没有修改过,如果没有的话应该返回0
*/
min = Math.min(min, right - left + 1);
left++;
sum -= nums[left - 1];
flag = false;
}
/**
* 如果right已经到达右边界但是和还是小于target,说明已经没有满足的区间了,可以直接结束循环了
*/
else if (sum < target && right == nums.length - 1){
break;
}
else {
/**
* 如果right已经到达右边界,就不应该再增加了
*/
if (right + 1 < nums.length) {
right++;
sum += nums[right];
}
}
}
return flag == false ? min : 0;
}
}
/**
* 时间复杂度 O(n)
* 空间复杂度 O(1)
*/
优化1——简化循环的判定、不使用标志位
class Solution {
public int minSubArrayLen(int target, int[] nums) {
/**
* 滑动窗口
* 两个指针同向移动,如果当前窗口内的元素和大于target就记录长度,然后left指针右移缩小查找范围
* 如果小于target,right指针右移扩大查找范围
*/
int left = 0;
int right = 0;
int min = nums.length + 1;
int sum = nums[0];
/**
* 如果left > right,说明有一个元素大于target,那就不需要再循环了,因为最小长度就是1
*/
while (left <= right){
if (sum >= target){
min = Math.min(min, right - left + 1);
sum -= nums[left++];
}
else {
/**
* 如果right已经到达右边界,就不应该再增加了
*/
if (right + 1 < nums.length) {
sum += nums[++right];
}
else {
/**
* 如果right已经到达右边界但和还是小于target,说明已经没有满足的区间了,可以直接结束循环了
*/
break;
}
}
}
/**
* 如果min没有变过,应该返回0
*/
return min == nums.length + 1 ? 0 : min;
}
}
/**
* 时间复杂度 O(n)
* 空间复杂度 O(1)
*/
https://leetcode-cn.com/problems/minimum-size-subarray-sum/