(LeetCode 面试经典 150 题 ) 76. 最小覆盖子串(哈希表+双指针)

题目:76. 最小覆盖子串

在这里插入图片描述
在这里插入图片描述

思路:双指针+哈希表,时间复杂度0(n+m)。

哈希表记录字符串t中字符出现的情况,ans记录字符的种类数。
使用双指针去遍历字符串s,当ans为0时,说明双指针内的元素已覆盖字符串t的字符。那么只需维护左指针,使长度最短,细节看注释。

C++版本:

class Solution {
public:
    string minWindow(string s, string t) {
        if(t.size()>s.size()) return "";
        // 哈希表记录字符串t中字符出现的情况
        unordered_map<char,int> mp;
        // ans记录字符的种类数
        int ans=0;
        for(auto x:t){
            mp[x]++;
            if(mp[x]==1) ans++;
        }
        // id是符合要求的子串起始下标,mn是最短的子串
        int id=-1,mn=s.size()+5;
        for(int l=0,r=0;r<s.size();r++){
        	//双指针内的元素减1
            mp[s[r]]--;
            // 为0,说明此字符的数量要求已达标
            if(mp[s[r]]==0) ans--;
            //cout<<l<<'-'<<r<<endl;
            // 如果左指针的元素数量小于0,说明这个元素不需要这么多
            while(l<r&&mp[s[l]]<0){
                mp[s[l]]++;
                l++;
            }
            // 双指针内的元素已覆盖字符串t的字符
            // 维护最短的子串
            if(ans==0&&mn>r-l+1){
                mn=r-l+1;
                id=l;
            }

        }
        if(id==-1) return "";
        return s.substr(id,mn);
    }
};

JAVA版本:

class Solution {
    public String minWindow(String s, String t) {
        if(t.length()>s.length()) return "";
        Map<Character,Integer> mp=new HashMap<>();
        int ans=0;
        char[] c=t.toCharArray();
        for(char x:c){
            mp.put(x,mp.getOrDefault(x,0)+1);
            if(mp.get(x)==1) ans++;
        }
        //System.out.println(ans);
        c=s.toCharArray();
        int id=-1,mn=s.length()+5;
        for(int l=0,r=0;r<c.length;r++){
            mp.put(c[r],mp.getOrDefault(c[r],0)-1);
            if(mp.get(c[r])==0) ans--;
            //System.out.println(l+" "+r+" "+ans);
            while(l<r&&mp.get(c[l])<0){
                mp.put(c[l],mp.getOrDefault(c[l],0)+1);
                l++;
            }
            if(ans==0&&mn>r-l+1){
                mn=r-l+1;
                id=l;
            }

        }
        if(id==-1) return "";
        return s.substring(id,id+mn);
    }
}

GO版本:

func minWindow(s string, t string) string {
    n:=len(s)
    mp:=map[byte]int{}
    ans:=0
    for i:=0;i<len(t);i++ {
        mp[t[i]]++
        if mp[t[i]]==1 {
            ans++
        }
    }
    id,mn:=-1,n+5
    for l,r:=0,0;r<n;r++ {
        mp[s[r]]--;
        if mp[s[r]]==0 {
            ans--
        }
        for l<r&&mp[s[l]] < 0 {
            mp[s[l]]++
            l++;
        }
        if ans==0 &&mn>r-l+1 {
            mn=r-l+1
            id=l
        }
    }
    if id==-1 {
        return string("")
    }
    return s[id:id+mn]
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值