【Minimum Window】cpp

题目:

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.

代码:

class Solution {
public:
    string minWindow(string s, string t) {
            if (s.empty() && t.empty() ) return "";
            if (s.size()<t.size()) return "";
            const int ASCII_MAX = 256;
            // record how much times a char occurs in t
            int t_char_count[ASCII_MAX] = {0};
            for ( int i=0; i<t.size(); ++i ) { t_char_count[(int)t[i]]++; }
            // record how much times a char occurs in s
            int s_char_count[ASCII_MAX] = {0};
            // global min begin and end index for minimum interval
            int begin_min=-1, end_min=s.size();
            // local min begin ( no need to record local min end ,because it is 'i' )
            int begin = 0;
            int match_size = 0;
            for ( int i=0; i<s.size(); ++i )
            {
                // current interval not match && current char in t
                if ( t_char_count[(int)s[i]]>0 )
                {
                    //cout << s[i] << ":" << t_char_count[s[i]] << endl;
                    s_char_count[(int)s[i]]++;
                    // if a char occurs more times in current interval s than in t, can not increase match_size
                    if ( s_char_count[(int)s[i]]<=t_char_count[(int)s[i]] ) match_size++;
                }
                if ( match_size==t.size() )
                {
                    // move begin forward untill not match
                    while ( begin<=i )
                    {
                        // only address chars not in t
                        if ( s_char_count[(int)s[begin]]>0 )
                        {
                            if ( s_char_count[(int)s[begin]]-1<t_char_count[(int)s[begin]] ) 
                            {
                                //cout << s_char_count[s[begin]] << endl; 
                                match_size--;
                                break;
                            }
                            s_char_count[(int)s[begin]]--;
                        }
                        begin++;
                    }
                    s_char_count[(int)s[begin]]--;
                    // update global min begin and end
                    if ( end_min-begin_min > i-begin ) { end_min = i; begin_min = begin; }
                    begin++;
                }
            }
            if( end_min-begin_min>s.size() ) return "";
            return s.substr(begin_min,end_min-begin_min+1);
    }
};

tips:

曾经以为这种题比较简答,实际上不带算法模板套路的题才是最费神的。

这道题一开始的思路是记录t中每个字符最左边到哪最右边到哪,然后再云云;这个想法不太靠谱。

如果是bruce force暴力解法,时间复杂度可以是O(n²)的:

1. 遍历每个位置,以每个位置为中心,往左右走,直到包含所有的元素,取最短的。

2. 取所有interval中最短的。

可以AC的解法思路如下:

1. 维护几个核心变量:

  a)t中每个字符出现了几次(t_char_count)

  b) s中当前区间里面,t中每个字符出现了几次(s_char_count)

  c) s当前区间是否满足包含t(match_size)

2. 这道题思路很有趣:先找满足包含t的区间;一旦找到了这样的区间,再缩小这样的区间。

  缩减区间的方法:后面的指针保持不动,前面的指针往后移动,直到match_size < t.size(),则证明当前区间已经是最小的满足条件的区间了。

3. 动态更新最小区间。

主要参考:

http://www.cnblogs.com/TenosDoIt/p/3461301.html

http://fisherlei.blogspot.sg/2012/12/leetcode-minimum-window-substring.html

============================================

第二次过这道题,静下心来码。

class Solution {
public:
    string minWindow(string s, string t) {
            int t_counts[256] = {0};
            int s_counts[256] = {0};
            for ( int i=0; i<t.size(); ++i ) t_counts[(int)t[i]]++;
            int matchTime = 0;
            int begin = -1;
            int end = s.size();
            int b = 0;
            for ( int i=0; i<s.size(); ++i )
            {
                // only address character occurs in string t
                if ( t_counts[(int)s[i]]>0 ) 
                {
                    s_counts[(int)s[i]]++;
                    // after s_count add one change matchTime
                    if ( s_counts[(int)s[i]]<=t_counts[(int)s[i]] ) matchTime++;
                }
                // when there is a window, then minimisze it
                if ( matchTime==t.size() )
                {
                    while ( b<=i )
                    {
                        // only address charatcers occurs in string t
                        if ( s_counts[(int)s[b]]>0 )
                        {
                            // if move over 'begin then 'can not keep window
                            if ( s_counts[(int)s[b]]-1 < t_counts[(int)s[b]] )
                            {
                                matchTime--;
                                break;
                            }
                            s_counts[(int)s[b]]--;
                        }
                        b++;
                    }
                    if ( i-b < end-begin )
                    {
                        begin = b;
                        end = i;
                    }
                    s_counts[(int)s[b]]--;
                    b++;
                }
            }
            if ( end-begin>s.size() ) return "";
            return s.substr(begin, end-begin+1);
    }
};

 

posted on 2015-06-08 15:13  承续缘  阅读(215)  评论(0编辑  收藏  举报

导航