leetcode——Minimum Window Substring

题目:

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 empty string "".

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

分析:

1、对T建立一个hash表hash_t,hash_t[ch]表示在T中字符ch出现的次数。

2、pBegin和pEnd是S中窗口的起止下标,维护窗口[pBegin, pEnd]的hash表hash_s,

      则窗口包含T中所有字符的充要条件是hash_s[ch] >= hash_t[ch]对任意ch成立。

3、流程:

    (1)初始化hash_t。

    (2)pBegin和pEnd指向S的起始位置,向后移动pEnd同时更新hash_s,直到窗口包含T中所有字符。

    (3)pBegin向后移动,更新窗口的位置和大小,直到不再满足包含条件,记录下导致包含条件丢失的字符ch。

    (4)pEnd向后移动并更新hash_s,直到再次包含(不再通过遍历并比较hash_s和hash_t来确定是否包含,而是pEnd指向ch)。

    (5)重复(3)(4)。

class Solution {
public:
    string minWindow(string s, string t) {
        int hash_t[256];//用来快速判断一个字符是不是属于t
        fill_n(hash_t, 256, 0);
        for (auto c : t)
        {
            hash_t[c]++;
        }

        int hash_s[256];//用来表示t的hash表
        fill_n(hash_s, 256, 0);

        //初始化
        int pBegin = 0, pEnd = 0;//后移pEnd,使得[pBegin, pEnd]包含t中的所有字符
        int sLen = s.length();
        while (pEnd < sLen)
        {
            hash_s[s[pEnd]]++;
            //判断[pBegin, pEnd]是否包含t中所有字符
            bool isContain = true;
            for (int i = 0; i < 256; ++i)
            {
                if (hash_s[i] < hash_t[i])
                {
                    isContain = false;
                    break;
                }
            }
            if (isContain)
            {
                break;
            }
            ++pEnd;
        }
        //t不是s的子集
        if (pEnd == sLen)
        {
            return "";
        }
        int win_start = pBegin;
        int win_size = pEnd - pBegin + 1;
        //pBegin向后收缩更新窗口
        while (true)
        {
            char ch = s[pBegin];
            ++pBegin;
            hash_s[ch]--;//从窗口中删除ch
            if (hash_s[ch] < hash_t[ch]) //删除ch后窗口不能contain了
            {
                bool found = false;
                for (pEnd++; pEnd < sLen; pEnd++)//pEnd向后查找ch,使得可以重新contain
                {
                    char c = s[pEnd];
                    hash_s[c]++;
                    if (c == ch)
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    break;//再也不能contain了,返回吧
                }
            }
            else //pBegin的收缩没有影响,更新win
            {
                //找到了,重新contain
                int new_win_size = pEnd - pBegin + 1;
                if (new_win_size < win_size)
                {
                    win_size = new_win_size;
                    win_start = pBegin;
                }
            }
        }
        return s.substr(win_start, win_size);
    }
};


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值