滑动窗口+哈希表:最小覆盖子串

力扣题目:最小覆盖子串

  1. 最小覆盖子串
    给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。

注意:

对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。

AC代码

class Solution {
public:
    string minWindow(string s, string t) 
    {
        unordered_map<char, int> hash;  // 键值对 键是字符 值是该字符出现次数

        for (int i = 0; i < t.size(); i ++ ) 
        {
            hash[t[i]] ++ ;
        }

        int left = 0, right = 0, n = s.size(), count = t.size();
        int min_length = 1e6, min_left = 1e6, min_right = 1e6;
        while (right < n)
        {
            // cout << "左边界,右边界为——" << left << "," << right << endl;
            // cout << "count为——" << count << endl;
            // 遍历到s[right]这个字符,判断t中是否需要有他
            if (hash.find(s[right]) != hash.end())    // 等于end的时候,表示未找到
            {
                if (hash[s[right]] >= 1) // 如果这个字符还需要出现的次数>=1
                {  
                    count -- ;  // 当count为0,则表示全找到了
                }   // 注意,可能等0 -1 -2,表示这个字符出现次数多了很多
                hash[s[right]] -- ;
                // cout << "s[right] = " << s[right] << endl;
                // cout << hash[s[right]] << endl;
            }

            
            while (count == 0)
            {
                // cout << "找到一个答案\n";
                // 每出现一次计数器为0,则表示当前长度内,是符合要求的,但可能不是最优
                if (right - left + 1 < min_length)
                {
                    // 更短,则更新答案
                    min_length = right - left + 1;
                    min_left = left;
                    min_right = right;
                }
                // 尝试左移left,看看能否符合条件并且缩小区间
                if (hash.find(s[left]) != hash.end())
                {
                    hash[s[left]] ++ ;
                    if (hash[s[left]] >= 1)
                    {
                        count ++ ;  // hash[字符]表示字符还需要出现的次数,0表示刚好,1表示还要1个,-1表示多了1个
                    }
                }
                left ++ ;
            }

            right ++ ;  // 窗口右边界后移
        }

        // cout << "min_length min_left min_right "  << min_length << min_left << " " << min_right << endl;
        string ret = "";
        if (min_length !=  1e6) ret = s.substr(min_left, min_length);
        return ret;
    }

    
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值