【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. 水果成篮 中等题

在这里插入图片描述
这里有坑,数不大于数组的数量

  • 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. 最小覆盖子串

在这里插入图片描述
滑动窗口的思想:
用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);
    }
}
  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值