> 文档中心 > 【LeetCode】滑动窗口

【LeetCode】滑动窗口


坚持内卷

209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。

在right循环里,left++
我的做法:

class Solution {    public int minSubArrayLen(int target, int[] nums) { int left = 0,right = 0, sub = 0,sum = 0,result = Integer.MAX_VALUE; for(right = 0;right <nums.length; right ++){     sum +=nums[right];     while(sum  >= target){  sub = right -left +1;  result = result < sub ?result :sub;  sum -= nums[left++];} } return  result ==  Integer.MAX_VALUE? 0 :result;    }}

不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被被操作两次,所以时间复杂度是 2 × n 也就是O(n)。

904. 水果成篮 中等题

【LeetCode】滑动窗口
这里有坑,数不大于数组的数量

  • 1 <= fruits.length <= 105
  • 0 <= fruits[i] < fruits.length
class Solution {    public int totalFruit(int[] fruits) { int left= 0,right = 0,count = 0; int [] i = new int[fruits.length]; int total = 0; if(fruits.length <=2){     return fruits.length; } for(right =0; right <fruits.length;right ++){    i[fruits[right]]  +=1;    if(i[fruits[right]] == 1)  count++;    while(count > 2){   //这里是while  而不是if i[fruits[left]] -=1; if(i[fruits[left]] == 0)  count--; left++;    }    total  = total >(right -left +1) ? total : (right -left +1); } return total;    }}

76. 最小覆盖子串

【LeetCode】滑动窗口
滑动窗口的思想:
用i,j表示滑动窗口的左边界和右边界,通过改变i,j来扩展和收缩滑动窗口,可以想象成一个窗口在字符串上游走,当这个窗口包含的元素满足条件,即包含字符串T的所有元素,记录下这个滑动窗口的长度j-i+1,这些长度中的最小值就是要求的结果。

步骤一
不断增加j使滑动窗口增大,直到窗口包含了T的所有元素

步骤二
不断增加i使滑动窗口缩小,因为是要求最小字串,所以将不必要的元素排除在外,使长度减小,直到碰到一个必须包含的元素,这个时候不能再扔了,再扔就不满足条件了,记录此时滑动窗口的长度,并保存最小值

步骤三
让i再增加一个位置,这个时候滑动窗口肯定不满足条件了,那么继续从步骤一开始执行,寻找新的满足条件的滑动窗口,如此反复,直到j超出了字符串S范围。

class Solution {    public String minWindow(String s, String t) { if(s =="" || s.length() == 0  || t == "" || t.length() == 0) return ""; int left = 0,right = 0, count = t.length(),size =Integer.MAX_VALUE,start =0; int [] need = new int[128]; for( int i = 0; i<t.length();i++){     need[t.charAt(i)] ++; } while(right <s.length()){    char c=  s.charAt(right);    if(need[c] >0){ count--; }    need[c]--;    if(count ==0){ while(left < right && need[s.charAt(left)] <0){     need[s.charAt(left)]++;     left++; } if(size>(right -left +1)){     size = right-left +1;     start = left; } need[s.charAt(left)]++; left++; count++;    }    right++; } return size ==Integer.MAX_VALUE ? "" :s.substring(start,start+size);    }}