[滑动窗口] LeetCode 76. 最小覆盖子串

76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

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

示例 2:

输入:s = "a", t = "a"
输出:"a"

提示:

1 <= s.length, t.length <= 10^5
s 和 t 由英文字母组成
  • 解题思路(双指针维护一个滑动窗口)


    • 先统计t字符串中的字符及个数;

    • 设置cntt的长度,是一共需要匹配的字符个数;

    • 扩大窗口,并判断当前字符是否可以匹配的上,如果匹配的上,则cnt--

    • cnt == 0说明已经完全匹配,此时需要扩大左边界,如果左边界的字符移出窗口导致不能够完全匹配(S[s[l]] < T[s[l]]),cnt++,当cnt > 0,此时判断是否需要更新答案。


C++版本

class Solution {
public:
    string minWindow(string s, string t) {
        int S[256] = {0},T[256] = {0};
        for(auto x : t) T[x]++;
        int n = s.size(),cnt = t.size(); //cnt是待匹配的字符的个数
        int len = n + 1,idx = -1; //idx是最小覆盖子串的起始下标,len是子串的长度
        for(int l = 0, r = 0; r < n; r++){
            S[s[r]]++;
            if(S[s[r]] <= T[s[r]]) //匹配上一个待匹配的字符
                cnt--;
            while(l <= r && cnt == 0){ //cnt == 0说明已经完全匹配成功
                S[s[l]]--;
                if(S[s[l]] < T[s[l]]) cnt++;
                if(cnt > 0) //如果cnt == 0 变成了小于0 则说明当前l-r的区间是完全匹配的,此时更新答案                  
                    if(len > r - l + 1) {
                        len = r - l + 1;
                        idx = l;
                    }
                l++; //缩短区间
            }
        }
        return idx == -1 ?  "" : s.substr(idx,len);
    }
};
Python版本
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        S = collections.Counter(t)
        cnt  = len(t)
        n = len(s)
        dic,l,r,res,Len = {},0,0,"", n + 1
        while r < n:
            if s[r] not in dic:
                dic[s[r]] = 1
            else:
                dic[s[r]] += 1
            if(dic[s[r]] <= S[s[r]]):
                cnt -= 1
            while l <= r and cnt == 0: #完全匹配,收缩窗口
                dic[s[l]] -= 1
                if dic[s[l]] < S[s[l]]:
                    cnt += 1
                    if cnt > 0:
                        if Len > r - l + 1:
                            res = s[l:r + 1]
                            Len = r - l + 1
                l += 1
            r += 1
        return res
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值