目录
-
描述

-
思路
B站大佬讲解

-
暴力破解
一个for循环,固定起始位置,一个for循环寻找符合条件的子数组,并记录长度
例如数组为a b c d e f
子数组 a,a+b,a+b+c>=target; break; length = 3
子数组 b,b+c,b+c+d,b+c+d+e>=target; break; 4>3 length=3
....
-
滑动窗口法
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
滑动窗口内是什么:符合条件的子数组
窗口的起始位置如何移动:窗口值>=s,起始位置就要向前移动了(也就是该缩小了)。
窗口的终止位置如何移动:窗口的终止位置就是遍历数组的指针,也就是for循环里的索引。
例如a+b+c<target,a+b+c+d>=target
暴力从b重新累加,但是可以进行优化。
b+c一定小于target ,所以我们直接看b+c+d是否>=target,也就是从上一个符合条件的子数组减去它的初始元素,相当于滑动窗口的起始位置向前移动一位。那么应该如何实现呢?
for循环里面是终止位置的索引 j
起始索引 为i=0; sum=0;
sum = sum+nums[j]
while(sum>=target),记录子序列长度并更新最小子序列长度,sum-nums[i];i++;//找到最短子数组
while和if的区别
while的作用:
当
sum >= target时,while会不断收缩左边界i,直到sum < target。这样可以确保找到以当前
j为右边界的最短子数组。
if的作用:
当
sum >= target时,if只会执行一次,收缩左边界i一次。这样无法确保找到以当前
j为右边界的最短子数组。为什么不能将
while改为if?如果将
while改为if,滑动窗口的逻辑会失效,具体表现为:
无法找到最短子数组:
if只会尝试收缩一次左边界,可能无法将窗口缩小到最小。例如,如果窗口内的和远大于
target,if只会减去一个元素,而while会不断减去元素,直到窗口内的和小于target。可能漏掉更短的子数组:
if只收缩一次,可能导致窗口仍然较大,从而漏掉更短的满足条件的子数组。

-
代码
暴力破解:
//暴力解 超时
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int min = Integer.MAX_VALUE;
int length=0;
for(int i=0;i<nums.length;i++){
int sum = nums[i];
if(sum>=target){
length = 1;
}
else{
for(int j=i+1;j<nums.length;j++){
sum += nums[j];
if(sum>=target){
length = j-i+1;
break;
}
}
}
if(length<min){
min = length;
}
}
return min==Integer.MAX_VALUE?0:min;
}
}
滑动窗口:
//滑动窗口
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int i=0;
int min=Integer.MAX_VALUE;
int length = 0;
int sum = 0;
for(int j=0;j<nums.length;j++){
sum+=nums[j];
while(sum>=target){
length = j-i+1;
if(length<min){
min = length;
}
sum = sum-nums[i];
i++;
}
}
return min==Integer.MAX_VALUE?0:min;
}
}

1万+

被折叠的 条评论
为什么被折叠?



