• [LeetCode]438. 找到字符串中所有字母异位词、76. 最小覆盖子串(滑动窗口解决子串问题系列)


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

    给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。

    说明:
    字母异位词指字母相同,但排列不同的字符串。
    不考虑答案输出的顺序。

    题解

    滑动窗口。

    数据结构

    准备两个HashMap,needs存模式串中各字符出现次数,window存待匹配串中(在needs中出现过的)各字符出现的次数。
    用match来计数量匹配对的字符数。

    具体方法

    • 维护滑动窗口的左右指针。
    • 右指针不断右移知道串包含了所有模式串中出现的字符,且出现次数大于等于其。
    • 然后在满足“包含了所有模式串中出现的字符,且出现次数大于等于其”的条件下,不断右移左指针,每次若长度等于模式串则找到一个所求串,每次右移左指针也要相应更新window和match。
    • 总体直到右指针到字符串结尾后结束,时间复杂度O(n).

    相关

    对象的相等比较要用obj1.equals(obj2),而不能用====比较的是对象地址。

    代码

    class Solution {
        public List<Integer> findAnagrams(String s, String p) {
            if(s==null||p==null){
                return null;
            }
            
            List<Integer> ansList=new ArrayList<Integer>();
            HashMap<Character,Integer> needs=new HashMap<>();
            HashMap<Character,Integer> window=new HashMap<>();
            
            for(int i=0;i<p.length();++i){
                needs.put(p.charAt(i),needs.getOrDefault(p.charAt(i),0)+1);
            }
            
            int l=0;
            int r=0;
            int matchCnt=0;
            int hopMatchCharCnt=needs.size();//
            while(r<s.length()){
                char c=s.charAt(r);
                if(needs.containsKey(c)){
                    window.put(c,window.getOrDefault(c,0)+1);
                    if(window.get(c).equals(needs.get(c))){
                        ++matchCnt;
                    }
                }
                
                while(matchCnt==hopMatchCharCnt){//
                    if(r-l+1==p.length()){//
                        ansList.add(l);
                    }
                    
                    //包含子串情况下l不断右移
                    char leftC=s.charAt(l);//
                    if(window.containsKey(leftC)){
                        window.put(leftC,window.get(leftC)-1);//
                        if(window.get(leftC)<needs.get(leftC)){
                            --matchCnt;
                        }
                    }
                    ++l;
                }
                
                ++r;
            }
            return ansList;
        }
    }
    

    题目76. 最小覆盖子串

    给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。

    题解

    和上面基本一模一样==,改个返回即可。

    代码

    class Solution {
        public String minWindow(String s, String t) {
            if(s==null||t==null){
                return "";
            }
            
            HashMap<Character,Integer> needs=new HashMap<>();
            HashMap<Character,Integer> window=new HashMap<>();
            
            for(int i=0;i<t.length();++i){
                needs.put(t.charAt(i),needs.getOrDefault(t.charAt(i),0)+1);
            }
            
            int l=0;
            int r=0;
            int matchCnt=0;
            int hopMatchCharCnt=needs.size();//
            
            int minLen=Integer.MAX_VALUE;
            int ansBeg=0;
            
            while(r<s.length()){
                char c=s.charAt(r);
                if(needs.containsKey(c)){
                    window.put(c,window.getOrDefault(c,0)+1);
                    if(window.get(c).equals(needs.get(c))){
                        ++matchCnt;
                    }
                }
                
                while(matchCnt==hopMatchCharCnt){//
                    if(r-l+1<minLen){//
                        ansBeg=l;
                        minLen=r-l+1;
                    }
                    
                    //包含子串情况下l不断右移
                    char leftC=s.charAt(l);//
                    if(window.containsKey(leftC)){
                        window.put(leftC,window.get(leftC)-1);//
                        if(window.get(leftC)<needs.get(leftC)){
                            --matchCnt;
                        }
                    }
                    ++l;
                }
                
                ++r;
            }
            return minLen==Integer.MAX_VALUE?"":s.substring(ansBeg,ansBeg+minLen);
        }
    }
    
  • 相关阅读:
    [网络流24题]方格取数
    [网络流24题]太空飞行计划
    网络流24题题解合集【不定期更新】【附常见套路分析】
    【优先队列】POJ3614-Sunscreen
    【优先队列】POJ1442-Black Box
    【Huffman树贪心+优先队列】POJ3253-Fence Repair
    【优先队列+贪心】POJ2431-Expedition
    【专题笔记】优先队列和堆
    【动态规划】POJ1664-放苹果
    【动态规划+二分查找】POJ2533&POJ1631最长上升子序列(LIS)
  • 原文地址:https://www.cnblogs.com/coding-gaga/p/11324629.html
Copyright © 2020-2023  润新知