最小窗口子串

题目描述

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,
S ="ADOBECODEBANC"
T ="ABC"

Minimum window is"BANC".

Note:
If there is no such window in S that covers all characters in T, return the emtpy string"".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S. 

给定一个字符串source和一个目标字符串target,在字符串source找到包括所有目标字符串字母的最小子串。

 注意事项

如果在source没有这样的子串,返回"",如果有多个这样的子串,返回长度最小的子串。

说明

在答案的子串中的字母在目标字符串中是否需要具有相同的顺序?

——不需要。

样例

给出source = "ADOBECODEBANC"target = "ABC" 满足要求的解  "BANC"

挑战

要求时间复杂度为O(n)


这道题的要求是要在O(n)的时间度里实现找到这个最小窗口字串,那么暴力搜索Brute Force肯定是不能用的,我们可以考虑哈希表,其中key是T中的字符,value是该字符出现的次数。

- 我们最开始先扫描一遍T,把对应的字符及其出现的次数存到哈希表中。

- 然后开始遍历S,遇到T中的字符,就把对应的哈希表中的value减一,直到包含了T中的所有的字符,纪录一个字串并更新最小字串值。

- 将子窗口的左边界向右移,略掉不在T中的字符(更新最小子串),如果子窗口中某个在T中的字符出现的次数大于哈希表中的value,则也可以跳过该字符。

实现代码:

             class Solution {
public:
    string minWindow(string S, string T) {
        if (T.size() > S.size()) return "";
        string res = "";
        int left = 0, count = 0, minLen = S.size() + 1;//left为左边界,默认最小子串长度;
        unordered_map<char, int> m;    //map容器作为hash表;
        for (int i = 0; i < T.size(); ++i) 
        {
            if (m.find(T[i]) != m.end())     //将目标串存入哈希表;
                ++m[T[i]];
            else 
                m[T[i]] = 1;
        }
        for (int right = 0; right < S.size(); ++right) 
        {
            if (m.find(S[right]) != m.end())   //判断S[right]是不是位于hash表中;
            {
                --m[S[right]];
                if (m[S[right]] >= 0) ++count; //计数值作为T中字符已经出现的个数;
                while (count == T.size()) //如果找到所有目标字符;
                {
                    if (right - left + 1 < minLen) 
                    {
                        minLen = right - left + 1;   //更新最小长度
                        res = S.substr(left, minLen); //取出该最小字符;
                    }
                    if (m.find(S[left]) != m.end()) //左边界判断,S[left]不在m中就省略掉;
                    {
                        ++m[S[left]];   //S[left]在m中,恢复m[S[left]]的值;
                        if (m[S[left]] > 0) --count; //恢复之后若大于0,那么就略掉了一个有用的字符;计数值要减一;继续向后遍历;
                        //如果该子串中某个在T中的字符出现的次数大于哈希表中的value,则也可以跳过该重复字符;
                    }
                    ++left;   //左边界移动;
                }
            }
        }
        return res;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值