【LeetCode】76. Minimum Window Substring

来源:互联网 发布:诺基亚java下载专区 编辑:程序博客网 时间:2024/05/20 17:59

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".

Note:
If there is no such window in S that covers all characters in T, return the empty string "".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.


【分析】

    题意:从给定字符串S中寻找包含给定字符串T中所有字母的最小子串。

    既然是寻找最小子串,遍历字符串S不可避免,在遍历S中每一个字符时,我们需判断该字符是否为T中所含字符,考虑到字符存在重复的可能,在遍历S时还需判断所包含T中存在的字符的出现次数,鉴于此,我采用了“哈希表”来记录T中所包含的字符及其数量,如此可以极大程度的简化判断,具体操作为:

    1、由于给定字符串只包含大小写字母,其ASCII范围为[65,90],[97,122],为避免作差,哈希表长度可设为128,对于T中第i个字符对应哈希表的存储位置下标为:T[i];事实上哈希表的长度可以是57=122-65,但如此一来,T中第i个字符对应哈希表的存储位置下标为T[i]-'A',可根据空间、时间的重要性选择其一;

    2、对字符串T进行一次遍历,便可以通过哈希表记录其包含的字符及其数量;

    3、然后我们对字符串S进行遍历,建立一个滑动窗口,首尾指针初始化为begin=end=0,当遍历至第end+1个字符时,如果此时滑动串口[begin, end]第一次包含T中所有字符(包括次数),记录子串长度;

    4、此后,逐步压缩首指针begin,并更新最小子串长度,直到该窗口不能完全包含T中字符,停止移动begin,改为移动end;当窗口再一次包含T中所有字符时,重复上述步骤,直到end指向S末尾且begin压缩至不能完全包含T中所有字符为止;

    5、最后,将记录的最小窗口的字符串返回即可。

【解法及注释】

class Solution {public:    string minWindow(string s, string t) {                vector<int> count(60,0);//记录T中所包含字符及数量的哈希表,这个哈希表采用数组建立        vector<bool> flag(60,false);//标记T中所包含字符        int sum=t.size();//t中字符总数        int copyBegin=0;//最小子串首端        int begin=0;//滑动窗口首尾指针        int end=0;        int minsize=s.size()+1;//若出现s不能完全包含t的情况,最小子串不存在,但只要存在其长度必然<=s.size()                for(int i=0;i<t.size();i++)//遍历字符串t,标记其包含字符,记录其数量        {            count[t[i]-'A']++;            flag[t[i]-'A']=true;        }                for(int j=0;j<s.size();j++)//遍历字符串s        {            if(flag[s[j]-'A'])//判断s中字符是否为t中字符,若是,减去相应记录            {                count[s[j]-'A']--;//如果对应值小于零,则说明该字符在s中的数量多于t                if(count[s[j]-'A']>=0)//s中包含的某个字符可能多于t中存在的该字符,一旦记录==0,后续重复不应再考虑                sum--;            }                                    while(sum==0)//当窗口包含t中所有字符及数量            {                if(end-begin+1<minsize)//记录最小串长和最小串首端                {                  minsize=end-begin+1;                  copyBegin=begin;                }                                if(flag[s[begin]-'A'])//压缩窗口首端begin时,如果出现首端元素为t中字符,则需判断                {                  count[s[begin]-'A']++;                  if(count[s[begin]-'A']>0)//如果对应值小于零,说明该字符重复过多,无需考虑                  sum++;                   //反之,当前窗口不能完全包含t中字符,while()循环条件不再满足,end后移                }                begin++;//压缩首端            }            end++;        }        if(minsize>s.size())return "";//特殊情况,返回空        else return s.substr(copyBegin,minsize);//返回最小子串            }};


1 0
原创粉丝点击