[滑动窗口小结]关于滑动窗口的大致模板

该类题型模板:外层都是以右边界为对象进行移动,右边界每移动一次,对左边界进行移动和分析,并且检查结果是否需要更新(调用Math.max/min()函数);

模板其实都是一样的,可能会加入其他考点如哈希表的使用等等;

209.长度最小的子数组
题目链接

这里的时间复杂度,只需要看指针们的移动量,因为左右指针最多移动n次,即2n,复杂度为O(n)

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int ans=Integer.MAX_VALUE;
        int start=0;int end=0;int sum=0;
        while(end<nums.length){
            sum+=nums[end];
            
            while(sum>=target){
                ans=Math.min(ans, end-start+1);
                sum-=nums[start++];
            }
            end++;//放哪里?????——其始终指向sum序列中的首元素和末尾元素
        }

        return ans==Integer.MAX_VALUE ? 0:ans;
    }
}
904.水果成篮
题目链接
说人话其实就是找最长的含有两个元素的字符串(数组);
个人过不来的点:不知道如何快速找出一个字符串是否有两个元素:使用哈希表;
class Solution {
    public int totalFruit(int[] fruits) {
        int ans=Integer.MIN_VALUE;
        int start=0;int end=0;
        Map<Integer, Integer> cnt=new HashMap<Integer, Integer>(); 
        //该哈希表左侧是水果种类序号,右侧是该种水果出现的次数


        for(; end<fruits.length; end++){//end
           cnt.put(fruits[end], cnt.getOrDefault(fruits[end], 0)+1);
           while(cnt.size()>2){
            cnt.put(fruits[start], cnt.get(fruits[start])-1);
            if(cnt.get(fruits[start])==0){
                cnt.remove(fruits[start]);
            }
            start++;
           }
           ans=Math.max(ans, end-start+1);
        }

        return ans==Integer.MIN_VALUE?0:ans;
    }
}
76.最小覆盖子串

题目链接

 Tips

这里我发现一个很好用的刷题方法

当刷完前两道题,基本已经对滑动窗口的模板有了大致了解,在刷其他题目同题型题目时,可以先写出思路(伪代码),然后写下自己当时过不来的点,再看题解,看看别人是怎么做的:

比如这道题,我就是不知道右边界移动起来如何体现(如何收缩窗口)

 看了力扣的官方题解视频后,使用的他的思路:

class Solution {
    public String minWindow(String s, String t) {
         //结果所需变量
        int begin=0,length=s.length()+1;

        //原始字符串转换为数组
        char[] ss=s.toCharArray();
        char[] tt=t.toCharArray();

        //准备频率数组
        int sarr_num[]=new int[128];
        int tarr_num[]=new int[128];
        for(int i=0; i<tt.length; i++){
            tarr_num[tt[i]]++;
        }

        //[left, right)
        int left=0,right=0;
        int distance=0;//similar like海明距
        //开始挪动右边界
        while(right<ss.length){
            if(tarr_num[ss[right]]==0){
                right++;
                continue;
            }
            if(sarr_num[ss[right]]<tarr_num[ss[right]]){
                distance++;
            }
            sarr_num[ss[right]]++;
            right++;

            //左边界的移动
            while(distance==tt.length){
                if(right-left<length){
                    begin=left;
                    length=right-left;
                }

                if(tarr_num[ss[left]]==0){
                    left++;
                    continue;
                }
                if(sarr_num[ss[left]]==tarr_num[ss[left]]){
                    distance--;
                }
                sarr_num[ss[left]]--;
                left++;
            }
        }

        //返回元素,不要忘记不存在的情况
        if(length==ss.length+1) return "";
        else return s.substring(begin, begin+length);
    }
}
三道滑动窗口,其实都是一个模板

三道题不同之处在于: 

第一道题直接套用,没有其他考点

第二道题考到了哈希表

第三道题考到了哈希表的变式:ASCII码只有128个,所以只需要一个长度为128的数组来作为桶排序的“桶名”(不准确,但差不多这个意思)另外,还需要注意第三题数组可以乱序,可以出现多次,都需要体现在算法中,这也是选择哈希数组的原因(因为Java自带的HashMap只能记录键值和实际值,无法记录出现次数)


 
  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值