长度最小的子数组-滑动窗口解法
本来觉得自己双指针学的还可以了,于是今天直接刷了一道滑动窗口题,没想到还是被坑绊倒了两次。这次我想记录在博客里,不仅可以防止我以后重蹈覆辙,兴许也还可以帮助到其他人。
题目来自力扣:209. 长度最小的子数组 - 力扣(LeetCode)
最一开始,以为自己双指针学的很好,刚好也可以用到这道题上。于是有了思路:定义两个指针,一个指针走的快,一个指针走的慢。初始化sum=0用来记录两个指针走过的数组和。快指针先走,快指针每走一个数就将其存入sum中,直到sum>=target就停下,记录len=Math.min(len,i-j+1),然后慢指针开始向后遍历数组,并让快指针回到慢指针的位置,重复之间的动作。这个方法就是暴力解法,也是我陷入的第一个固定思维。
代码如下:
public int minSubArrayLen(int s, int[] nums) {
int sum=0;
int len=0;
for (int j=0;j<nums.length;j++){
int i=j;
while(i<=nums.length){
if (sum<s){
sum+=nums[i++];
}else {
len=Math.min(len,i-j+1);
}
}
}
return len;
}
这个误区在于,我没有正确认识到要把哪个指针放到while中,如果是把快指针放入while中,那如果sum>target,直接让sum减掉num[慢指针]就好了呀,这样慢指针也只需要遍历一次。
代码如下:
public int minSubArrayLen2(int s, int[] nums) {
int sum=0;
int len=Integer.MAX_VALUE;
int start=0;
for (int end=0;end<nums.length;end++){
sum+=nums[end];
while (sum>=s){
len=Math.min(len,end-start+1);
sum-=nums[start];
start++;
}
}
return len==Integer.MAX_VALUE?0:len;
}
注意:要用while (sum>=s)而不是if (sum>=s)。因为要一直让快指针走,直到sum>=s后,慢指针才能向前走。