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

自然的想法是从左向右扫,将S[i]加入window。当window满足条件时,尝试从window头踢字符(为了使window最小),然后每次取最小值。
问题的难点就是判断当前window是否包含T的所有字符。然后想到的是看做两个集合的包含关系的判断:
1. 用两个bitset做。后来发现这样只能判断是否含有T的所有字符种类。卒~
2. 用两个map做。当时这样做很慢,180ms~
其实在做法2的基础上改进很多。例如我们可以只用一个map,扫描T时map[T[i]] -= 1;扫描S时,map[S[i]] += 1。当map的每个value都大于等于0时,则表明当前window是包含T的所有字符的。进一步地,可以设置一个counter变量来记录window比T少的字符个数,然后每次检查counter就可以得知window是否合法。具体见代码二。

//代码一
class Solution {
public:
    inline bool isContain(map<char, int>& ss, map<char, int>& tt){
        for (auto it = tt.begin(); it != tt.end();++it){
            if (ss[(it->first)] < (it->second))
                return false;
        }
        return true;
    }
    string minWindow(string s, string t) {
        if (s.size() < t.size() || s.empty() || t.empty()) return "";
        map<char, int> ss, tt;
        for (char &c : t){
            ++tt[c];
        }

        int start = 0, l = -1, r = s.size();

        bool flag = false;
        for (int i = 0;i < s.size();++i){
            ++ss[s[i]];
            if (isContain(ss, tt)){
                flag = true;
                do{
                    --ss[s[start]];
                    ++start;
                }while (isContain(ss,tt));
                --start;
                ++ss[s[start]];
                if (i-start < r-l){
                    l = start;
                    r = i;
                }
            }

        }
        if (flag)
            return s.substr(l, r-l+1);
        else
            return "";

    }
};
//代码二
//由于ASCII编码只有128个字符,所以可以用一个int[128]来代替map
class Solution {
public:
    string minWindow(string s, string t) {
        int n=s.size();
        int m=t.size();
        if(n<1 || m<1 || n<m)
            return string("");
        int map[255]={0};
        for(char c: t)
            map[c]--;

        int counter=-m;
        int begin=0;
        int end=0;
        int d=n+1;
        int head=0;
        while(end<n)
        {
            if(map[s[end]]<0)
            { 
                counter++;
            }
            map[s[end]]++;
            end++;

            while(counter==0)
            {
                if(d>end-begin)
                {
                    d=end-begin;
                    head=begin;
                }
                if(map[s[begin]]==0) counter--;
                map[s[begin]]--;                    
                begin++;
            }
        }
        if(d==n+1)
            return string("");
        return string(s, head, d);
    }
};

猜你喜欢

转载自blog.csdn.net/guojunxiu/article/details/80217923