方法一:暴力解法双循环,据说会被力扣判断超时
方法二:滑动窗口(类似双指针)
class Solution {
// 滑动窗口
public int minSubArrayLen(int s, int[] nums) {
int left = 0;
int sum = 0;
//关于这里为什么最好不用nums.length作为result初始化的值:
//如果不存在满足条件的子数组,那result的值就不会被修改,仍然是nums.length
//如果满足条件的最小子数组就是nums[]本身,那result的值还是nums.length
//所以,int result = nums.length的做法会让返回值有很大的欺骗性,需要额外做一次判断区分这两种情况
//----我曾经考虑过,看着Integer.MAX_VALUE心里不舒服的话,初始值可以用nums.length+1,
//----但是对于一个很长的数组,我们不输出nums.length的话,其实nums.length+1的结果欺骗性还是很大,
//----需要额外加个if语句判断result是否小于nums.length+1,满足才是合法输出
//----为了省事还是用Integer.MAX_VALUE好了
int result = Integer.MAX_VALUE;
for (int right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= s) {
//比较窗口滑动之后的子数组长度是否变小
result = Math.min(result, right - left + 1);
sum -= nums[left++];
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
关于这里为什么最好不用nums.length作为result初始化的值:
如果不存在满足条件的子数组,那result的值就不会被修改,仍然是nums.length。如果满足条件的最小子数组就是nums[]本身,那result的值还是nums.length。
所以,int result = nums.length的做法会让返回值有很大的欺骗性,需要额外做一次判断区分这两种情况。我曾经考虑过,看着Integer.MAX_VALUE心里不舒服的话,初始值可以用nums.length+1,但是对于一个很长的数组,我们不输出nums.length的话,其实nums.length+1的结果欺骗性还是很大,需要额外加个if语句判断result是否小于nums.length+1,满足才是合法输出为了省事还是用Integer.MAX_VALUE好了。
方法二(犟驴版之我就不想用MAX_VALUE)
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0;
int right = 0;
int result = nums.length+1;
int sum = 0;
for(;right<nums.length;right++){
sum += nums[right];
//考虑窗口右移一位之后左侧可能会移动好几位,所以这里用while循环而不是if
//比如[1,1,1,1,100] target = 100的情况
while(sum>=target){
// 更新子数组长度
result = result > (right-left+1) ? (right-left+1) : result;
//result = Math.min(result,right-left+1);
//右移左指针
sum = sum -nums[left];
left++;
//sum -= nums[left++];
}
}
return result < nums.length + 1 ? result:0;
}
}
result 初始化为nums.length+1代码可读性可能不如MAX_VALUE,但是自己想出来的东西应该会记得更牢一些。