【LeetCode】76. 最小覆盖子串

题目链接:76. 最小覆盖子串
题目描述:给你一个字符串 s s s 、一个字符串 t t t。返回 s s s 中涵盖 t t t所有字符的最小子串。如果 s s s中不存在涵盖 $t $所有字符的子串,则返回空字符串 “” 。

注意:如果 s s s 中存在这样的子串,我们保证它是唯一的答案。

样例:

样例1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"

样例2:
输入:s = "a", t = "a"
输出:"a"

样例3:
输入:s = "a", t = "aa"
输出:""

数据范围:
1 <= s.length, t.length <= 10^5,s 和 t 由英文字母组成。
解题思路:这个题和上一题面试题 17.18. 最短超串十分类似,所不同的就是上一题中目标串中每个元素保证不相同,这题难就难在处理这个地方,其余与上个题思路保持一致。
  维护窗口和上题保持一致,至于什么时候缩小窗口,这里采用一个变量count来记录窗口中目标串的字符出现种类以及次数相匹配的个数(也就是说不仅仅是种类,每种字符对应的个数也要相等),当找到满足条件窗口时候,我们需要移动区间左指针L,移动之前要对count进行重新计数,如果当前L位置字符是目标串中的字符,并且其个数也相等,那么移动之后就不相等了,count需要自减。为什么不是目标串中包含这个字符count就自减,因为在中间过程中L位置的字符可能会增加,此时自减就会出错。

注意:需要注意的是在判断字符个数是否相等时候勿用==,这是因为Integer自身比较==的时候是有一个缓存在[-128,127]的,当map中value的值超过这个区间时候,==就会变为引用比较,换为equals即可,因为Integer重写了equals方法将其变为值比较。
代码:

class Solution {
    
    
        public String minWindow(String s, String t) {
    
    
        int n=s.length(),m=t.length();
        if(n<m) return "";
        HashMap<Character,Integer> maps=new HashMap<>();//记录目标串本身及出现次数
        HashMap<Character,Integer> mapCount=new HashMap<>();//记录窗口中目标字符及出现次数
        for(int i=0;i<m;i++) maps.put(t.charAt(i),maps.getOrDefault(t.charAt(i),0)+1);
        int L=0,R=0;
        int minWindowSize=n+1;
        int flag=0;
        int ansL=0,ansR=0;
        int count=0;
        for(R=0;R<n;R++){
    
    
            if(maps.containsKey(s.charAt(R))){
    
    
                mapCount.put(s.charAt(R),mapCount.getOrDefault(s.charAt(R),0)+1);
                if(mapCount.get(s.charAt(R)).equals(maps.get(s.charAt(R)))){
    
    
                    count++;
                }
            }
            while(maps.size()==count){
    
     //字符种类以及对应数目相同,开始移动L指针
                if(mapCount.containsKey(s.charAt(L))) {
    
    
                    if(mapCount.get(s.charAt(L)).equals(maps.get(s.charAt(L)))){
    
     //当前L位置要移动了,如果两个map的值相等,此时就需要自减了
                        count--;
                    }
                    mapCount.put(s.charAt(L),mapCount.get(s.charAt(L))-1);
                    if(mapCount.get(s.charAt(L))==0){
    
    
                        mapCount.remove(s.charAt(L));
                    }
                }
                L++;
                flag=1;
            }
            if(flag==1&&(R-L+1)<minWindowSize){
    
     //多个答案记录最小窗口的
                ansL=L-1;
                ansR=R;
                minWindowSize=ansR-ansL+1;
                flag=0;
            }
        }
        return minWindowSize==(n+1)?"" : s.substring(ansL,ansR+1);
    }
}

猜你喜欢

转载自blog.csdn.net/dl962454/article/details/114042054