[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 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). 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值