LeetCode Algorithms 76. 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”.

题目大意:找到S中最小的连续子串,把T中的所有字符都包含一次(注意重复的字符需要包含多次),要求找到最小的子串。

首先想到暴力的解法,就是遍历s中的字符,每匹配到t中的字符都循环遍历去匹配下一个字符,直到匹配了所有的字符,然后再看是否是最短的子串。这样复杂明显就很高,不符合题目要求。

所以我就想能不能遍历一次,然后得到一些信息从而把最短子串构造出来呢。我们只关心T的字符出现在S中的位置,所以不必要的字符的信息是不需要记录的,所以我想到用map去记录T中的字符在S中出现的index,用一个数组去保存这些index,然后根据多个字符的index,构造出最短的能包含T的子串头尾位置。

所以问题就转化为从几个数组里面取元素,找到拼起来后距离最短的元素集合。这样似乎很合理,但是很快就发现有的问题很难解决,比如现在找到一个组合的index是{2, 4, 5, 8},长度是7,那么如果现在第一个字符对应的数组第二个index是10,但是因为不够短,而无法判断是否要用这个10替换掉2这个数字。这会影响到后来的计算。

记录index的做法行不通,但是这种方法带给了我启发,我还是记录index,不过只记录子串头尾的index,然后使用一个数组去记录T中的元素在S中出现的次数,那么就可以通过移动子串头尾的index,来查找最短的包含T的字符的子串了。

具体方法参考了一下solution中的优秀解法:
1. 移动子串尾部,直到找到包含T中所有字符的子串
2. 移动子串头部,找在此基础上更小的子串

代码如下:

string minWindow(string s, string t) {
    vector<int> c(128, 0);// 记录字符出现次数
    int start = 0, end = 0, len = INT_MAX, count = t.size(), head;
    for (int i = 0; i < t.size(); i++) {
        c[t[i]]++;
    }
    while (end < s.size()) {
        /* 遍历到t中的字符后需要找的字符数-1 */
        if (c[s[end]] > 0) count--;
        c[s[end]]--;// -1代表该字符不在t中
        end++;
        /* 当t中所有字符都出现后 */
        while (count == 0) {
            if (end - start < len) {
                head = start;
                len = end - start;
            }
            if (c[s[start]]++ == 0) count++;// 头部后移的时候子串中缺少了t中某个元素
            start++;
        }
    }
    return len == INT_MAX ? "" : s.substr(head, len);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值