leetcode.76. 最小覆盖子串(双指针法)

题目:

给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。

示例:

输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"

说明:

  • 如果 S 中不存这样的子串,则返回空字符串 ""
  • 如果 S 中存在这样的子串,我们保证它是唯一的答案。

坑点:

1.在S中找到包含T中所有字母的子串,这个子串并不仅仅是要包含所有T中出现的字母种类,也要包含相对应的数量,如果T中有3个a,那么S的这个子串也需要有3个a才符合条件。

2.T的长度可能大于S的长度

思路:

1.如果T的长度大于S的长度,直接返回空。

2.用一个向量vector记录字符串T中出现的字母种类,用一个数组ans记录,T中每一个字母分别出现的次数。

3.如果判断s中的一个子串是否符合要求呢?如果对vetor中出现的元素(就是T字符串的字母种类),s子串中,这个字母出现的次数(用ch数组记录)都大于ans数组中的次数,则说明S这个子串符合要求。

4.对于S而言,用一个头指针i,尾指针j,s[j,i]之间就是s的一个子串,初始时i=j=0,然后i向前移动,直到s[j,i]符合要求,记录下此时子串的长度,如果长度小于原先记录的值,那么更新答案。然后往前移动j,这时候子串是否依然符合要求,如果符合,同样记得更新答案,并且j指针继续往前移动,直到不符合为止。

5.如果j指针不符合了,那么移动i指针,直到s[j,i]继续符合条件,此时,重复流程4,直到i指针到达S的末尾,答案在指针移动途中已经更新。

代码:

class Solution {
public:
int ch[300];
int ans[300];
vector<int>ve;
int num;
int maxx = 1e9;
bool pan(){
    int num = 0;
    int sz = ve.size();
    for(int i=0;i<sz;i++){
        if(ch[ve[i]]<ans[ve[i]]){
            return false;
        }
    }
    return true;
}



string minWindow(string s, string t) {
    int len = t.length();
    memset(ans,0,sizeof(ans));
    for(int i=0;i<len;i++){
        ans[t[i]]++;
    }

    for(int i=0;i<300;i++){
        if(ans[i]){ve.push_back(i);}
    }
    int len2 = s.length();
    if(len2<len)return "";
    memset(ch,0,sizeof(ch));
    int ma = maxx;
    int sta,en,i,j;
    for(i=0,j=0;i<len2;i++){
        ch[s[i]]++;
        while(pan()&&i>=j){
            if(ma>i-j){
                sta = j;
                en = i;
                ma = i-j+1;
            }
            ch[s[j]]--;
            j++;
        }

    }
    if(ma==maxx)return "";
    else return s.substr(sta,ma);
}


};

以上.

猜你喜欢

转载自blog.csdn.net/lwgkzl/article/details/81409873
今日推荐