牛客-最小覆盖字串

这题看题解看了好几次,每次看完会了之后过几天继续不会...蒟蒻惶恐

so决定这次留个痕迹,等下次不会了看看自己写的题解,找些回忆()...

给出两个字符串 s 和 t,要求在 s 中找出最短的包含 t 中所有字符的连续子串。

题目:

看完觉得和紫书上的”唯一的雪花“那道题很像,但是难多了qwq,,,

后来发现唯一相同的地方是双指针的设置上,均设置为为left=0,right=0,并且临界条件均为right<n。

这道题稍微人性化的一点是它问的是在s中找出包

含t中所有字符的连续子串,包含就说明是字母数量关系,不用进行顺序关系的判定(srds一个蒟蒻的脑子还是不会做)

既然是数量关系,一般就用两个map存,来进行数量的比对(因为map中的字母对应数量关系很明晰),而本题中的主体(最难part)的代码也如下所示:

​
        int letterCount = 0;
        //left,right快慢指针遍历字符串S
        int left = 0, right = 0;
        while (right < S.length()) {
            //用c标记当前字符串S走到的字符
            char c = S[right];
            if (mp.find(c) != mp.end()) {
                window[c]++;
                if (window[c] <= mp[c]) {
                    letterCount++;
                }
            }
            if (letterCount >= T.length()) {
                while (mp.find(S[left]) == mp.end() || window[S[left]] > mp[S[left]]) {
                    window[S[left]]--;
                    left++;
                }
                // minlength = min(minlength, right - left + 1);
                // res = S.substr(left, minlength);
                //我上面注释的部分是我第一次的错误写法,因为本题left随时都可能更新,所以要及时更新left与minlength对应的res
                if (right - left + 1 < minlength) {
                    minlength = right - left + 1;
                    res = S.substr(left, minlength);
                }
            }
            right++;
        }

​

完整代码(也不是完整,相对完整,在牛客上可以过的代码如下所示):

class Solution {
  public:
    /**
     *
     * @param S string字符串
     * @param T string字符串
     * @return string字符串
     */
    string minWindow(string S, string T) {
        string res;
        if (S.length() == 0 || T.length() == 0)
            return res;
        //两个哈希
        unordered_map<char, int>mp;//用来储存T中目标子串对应字母个数
        unordered_map<char, int>window;//用来储存S中与目标子串(要覆盖子串)相同字母对应个数
        //构造map
        for (int i = 0; i < T.length(); i++) {
            mp[T[i]]++;
        }
        int minlength = INT_MAX;
        //使用letterCount作为监视器,如果letterCount等于T.length()
        int letterCount = 0;
        //left,right快慢指针遍历字符串S
        int left = 0, right = 0;
        while (right < S.length()) {
            //用c标记当前字符串S走到的字符
            char c = S[right];
            if (mp.find(c) != mp.end()) {
                window[c]++;
                if (window[c] <= mp[c]) {
                    letterCount++;
                }
            }
            if (letterCount >= T.length()) {
                while (mp.find(S[left]) == mp.end() || window[S[left]] > mp[S[left]]) {
                    window[S[left]]--;
                    left++;
                }
                // minlength = min(minlength, right - left + 1);
                // res = S.substr(left, minlength);
                if (right - left + 1 < minlength) {
                    minlength = right - left + 1;
                    res = S.substr(left, minlength);
                }
            }
            right++;
        }
        return res;
    }
};

好啦!!记录完成,,,,希望可以带来帮助(to me)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值