滑动窗口法求解问题

变长滑动窗口法

求解思路:

1.使用双指针的技巧,初始化左右指针left,right,规定一个窗口;
2.第一个循环:首先滑动右指针,并更新状态(窗口内元素状态,及对题目要求是否满足等),直到窗口内的元素满足题目要求时进入第二个循环;
3.第二个循环:滑动左指针,并更新状态,知道窗口内的元素不满足题目要求时退出第二个循环;
4.重复2、3步,直到窗口不能再扩展。
tips:两个循环的状态是对称的,一个往窗口中添加元素,另一个从窗口中删除元素。

例题

76,最小覆盖子串


```java
class Solution {
    public static String minWindow(String s, String t){

        int minLeftIndex = -1;
        int minRightIndex = -1;

        int sLen = s.length();
        int tLen = t.length();
        // 如果slen<tlen,则不包含这样的子串
        if(sLen < tLen){
            return "";
        }

        // 变长滑动窗口
        int left = 0;
        int right = 0;//滑动窗口初始位置
        Map<Character,Integer> tMap = new HashMap<>();
        Map<Character,Integer> sMap = new HashMap<>();
        for (char c : t.toCharArray()) {
            int count = tMap.getOrDefault(c, 0)+1;
            tMap.put(c, count);
        }
        // valid记录还有多少个字符待匹配
        int valid = tMap.size();
        while(right < sLen){

            // 更新sMap中的内容
            char rightChar = s.charAt(right);
            right++;
            if(tMap.containsKey(rightChar)){
                sMap.put(rightChar,sMap.getOrDefault(rightChar, 0)+1);
                // 若需要的字符数量与已经包含的字符数量相等,
                if(sMap.get(rightChar).equals(tMap.get(rightChar))){
                    valid--;
                }

            }


            // 当当前窗口已经包含了t所有的字符,收缩窗口
            while(valid==0 && (right-left)>=tLen){

                if(minRightIndex == -1 || minRightIndex-minLeftIndex > right-left){
                    minLeftIndex = left;
                    minRightIndex = right;
                }

                char leftChar = s.charAt(left);

                if(tMap.containsKey(leftChar)){
                    if(sMap.get(leftChar).equals(tMap.get(leftChar))){
                        valid++;
                    }
                    sMap.put(leftChar,sMap.get(leftChar)-1);
                }

                left++;
            }

        }
        return minLeftIndex==-1 ? "" : s.substring(minLeftIndex,minRightIndex);


    }
}

56.字符串的排列


class Solution {
    public boolean checkInclusion(String s1, String s2) {
        int left = 0;
        int right = 0;
        Map<Character,Integer> map1 = new HashMap<>();
        Map<Character,Integer> map2 = new HashMap<>();
        for (char c : s1.toCharArray()) {
            map1.put(c, map1.getOrDefault(c, 0)+1);
        }
        // int valid = map1.size();
        int valid =0;
        while(right<s2.length()){
            char rightChar = s2.charAt(right);
            right++;
            if(map1.containsKey(rightChar)){
                map2.put(rightChar, map2.getOrDefault(rightChar, 0)+1);
                if(map1.get(rightChar).equals(map2.get(rightChar))){
                    valid++;
                }
            }
            

            while(right-left>=s1.length()){
                if(valid==map1.size()){
                    return true;
                }
                char leftChar = s2.charAt(left);
                if(map1.containsKey(leftChar)){
                    if(map1.get(leftChar).equals(map2.get(leftChar))){
                        valid--;
                    }
                    map2.put(leftChar, map2.get(leftChar)-1);
                }
                left++;

            }
        }
        return false;

    }
}


438.找到字符串中所有字母异位词

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();
        if(s.length()<p.length()){
            return res;
        }

        Map<Character,Integer> mapS = new HashMap<>();
        Map<Character,Integer> mapP = new HashMap<>();

        for(char c:p.toCharArray()){
            mapP.put(c, mapP.getOrDefault(c, 0)+1);
        }

        int left = 0;
        int right = 0;

        while(right<s.length()){
            char rightChar = s.charAt(right);
            right++;
            if(mapP.containsKey(rightChar)){
                mapS.put(rightChar, mapS.getOrDefault(rightChar, 0)+1);
            }
            while(right-left>=p.length()){
                if(mapP.equals(mapS)){
                    res.add(left);
                }
                char leftChar = s.charAt(left);
                if(mapP.containsKey(leftChar)){
                    mapS.put(leftChar, mapS.get(leftChar)-1);
                }
                left++;
            }
        }
        return res;



    }
}

3.无重复字符的最长子串

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character,Integer> map = new HashMap<>();
        int res = 0;

        int left = 0;
        int right = 0;
        // int index = 0;//上一次出现重复字符的位置
        while(right<s.length()){
            char rightChar = s.charAt(right);
            right++;
            if(!map.containsKey(rightChar)){
                map.put(rightChar, 1);
                res = res > (right - left) ? res : (right-left);
            }else{
                while(map.containsKey(rightChar)){
                    char leftChar = s.charAt(left);
                    left++;
                    // map.put(leftChar, map.get(leftChar)-1);
                    map.remove(leftChar, 1);
                }
                map.put(rightChar, 1);
            }
            
        }
        return res;


    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值