您的位置:首页 > 其它

[Leetcode] Minimum Window Substring

2014-11-06 11:43 309 查看
题目:

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.

思路:双指针。前面的指针向前扩展到包含所有字符为止,这个时候有些字符可能有冗余,例如目标字符串"ab",源字符串"aab",当窗口包含所有字符时字符a存在冗余;又或者窗口末端存在无关字符,例如目标字符串"ab",源字符串"cab"。无论哪种情况,在这个时候窗口都有可能被压缩,因此用后面的指针向前判断,直到压缩到不能再压缩为止。

        具体做法是,利用两个map,一个记录目标字符串每个字符的数量,另一个记录当前窗口中每个字符的数量,开始的时候两者是相等的。扩张的过程中,每当遇到目标字符串中的字符,则在当前窗口记录中将那个字符的数量减一。压缩的终止条件是,对于非相关字符,直接向前压缩,对于相关字符,判断剩余个数,如果小于0,说明有余量可以进行压缩,否则停止压缩,更新长度。

        其中的一个问题是,刚开始的时候,不可以进行压缩,需要先把所有字符都包括,然后再压缩。具体做法是,利用一个变量count记录目标字符串字符个数,在扩张的过程中,如果当前字符在目标字符串中,且当前窗口记录中该字符数量 ≥ 0,说明此次扩展囊括了一个有效字符,则count值减一;反例是目标字符串"ab",源字符串"aab",当扩张的第二个a时,a已经是-1了,说明第二个不是有效字符。当count为0时,即可以开始压缩。从这个时间节点往后,扩张和压缩即是动态进行,每扩张一个字符,进行一次压缩,同时更新窗口。

class Solution {
public:
    string minWindow(string S, string T) {
        int len = INT_MAX;
        string min_win = "";
        vector<int> src_record(256, 0);
        vector<int> cur_record(256, 0);
        for (int i = 0; i < T.size(); ++i) {
            src_record[T[i]]++;
            cur_record[T[i]]++;
        }
        int front = 0;
        int back = 0;
        int count = (int)T.size();
        for (; front < (int)S.size(); ++front) {
            if (src_record[S[front]] > 0) {   //the character is in T
                cur_record[S[front]]--;
                if (cur_record[S[front]] >= 0) {
                    count--;
                }
            }
            if (count == 0) {   //all characters in T are included
                // shrink the current window
                for (; back < front; ++back) {
                    if (src_record[S[back]] > 0) {
                        if (cur_record[S[back]] < 0) cur_record[S[back]]++;   //can shrink
                        else break;   //cannot shrink anymore
                    }
                }
                if (front - back + 1 < len) {   //update
                    len = front - back + 1;
                    min_win = S.substr(back, front - back + 1);
                }
            }
        }
        return min_win;
    }
};


总结:每个字符被两个指针访问一次,复杂度为O(n). 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: