滑动窗口算法

滑动窗口

核心是利用双指针维护一个不断变化的区间(维护一个窗口,不断滑动,然后更新答案)。

int left = 0, right = 0;  //初始化双指针

while (right < s.size()) {
    // 增大窗口
    window.add(s[right]);
    right++;
    // 进行窗口内数据的一系列更新
    
    while (window needs shrink) {
        // 缩小窗口
        window.remove(s[left]);
        left++;
         // 进行窗口内数据的一系列更新
    }
}

只需要思考以下几个问题

1、什么时候应该移动 right 扩大窗口?窗口加入字符时,应该更新哪些数据?

2、什么时候窗口应该暂停扩大,开始移动 left 缩小窗口?从窗口移出字符时,应该更新哪些数据?

3、我们要的结果应该在扩大窗口时还是缩小窗口时进行更新?

76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

class Solution {

    HashMap<Character,Integer> need = new HashMap<>(); //目标字符串所需有的字符
    HashMap<Character,Integer> window = new HashMap<>(); //窗口内有的字符
    public String minWindow(String s, String t) {
         
         boolean isSatisfied = false; // 窗口内有的字符是否满足
         String res = s; //所求字符串
         int right = -1, left = 0;  //窗口边界
         for(char c: t.toCharArray()) need.put(c,need.getOrDefault(c,0)+1); //装配目标字符

         while(right < s.length()-1){  //窗口滑动

            char c = s.charAt(++right); //窗口右边界延长
            window.put(c,window.getOrDefault(c,0)+1);  
            
            if(isSatisfied || check()){
            
                isSatisfied = true;
                while(true){
                    //从左边界缩小窗口
                    char cc = s.charAt(left);
                    window.put(cc,window.getOrDefault(cc,0)-1);  
                    if(check()){
                        //可以右移
                        left++;
                    }else{
                        window.put(cc,window.getOrDefault(cc,0)+1); //复原
                        break; //退出循环
                    }
                }
            }
            
            if(isSatisfied && right-left+1 < res.length()) res = s.substring(left, right+1);
 
         }
         return isSatisfied == true? res : "";
    }
    
    public boolean check(){
        for(Map.Entry<Character, Integer> entry: need.entrySet()){
            if(window.getOrDefault(entry.getKey(),0) < entry.getValue()){  //窗口中字符数量不满足条件
                return false;
            }
        }
        return true;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值