美文网首页
LeetCode 76 最小覆盖子串

LeetCode 76 最小覆盖子串

作者: Catcola | 来源:发表于2020-10-01 17:36 被阅读0次

题意:给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。


思路:这题要求O(n)的复杂度,首先想到用两个指针i,j遍历S串,找到满足条件的(j - i + 1)的最小值。问题在于怎么在O(1)的复杂度内判断S[i,j]包含T中所有的字符呢?

用一个mp数组记录T串中所有字符出现的次数,字符的ASCII码作为下标。(一开始以为只有大写字母,直接用字符-‘A’作为下标了)。并且统计T串中不同字符的个数cnt。

在遍历S串的时候,实时统计每个字符出现的次数,如果某个字符出现的次数等于mp[i],那么sum++,如果sum==cnt,说明这时候S[i,j]包含T串中所有字符的个数。i往后移,直到sum != cnt。

小小的剪枝:如果当前已经有满足条件的子串,并且j-i+1要比满足条件的子串的长度要长,i往后移,注意更新每个字符出现的次数。


C++代码:

class Solution {

public:

    int mp[200];

    string minWindow(string s, string t) {

        if(s.size() == 0 || t.size() == 0) return "";

        memset(mp, 0, sizeof(mp));

        int cnt = 0;

        for(int i = 0; i < t.size(); i++){

            if((int)mp[t[i]] == 0) cnt++; 

            mp[(int)t[i]] += 1;

        }

        int i = 0, j = 0;

        int reslen = -1;

        int resstart = -1;

        int tmp[200];

        int sum = 0;

        memset(tmp, 0, sizeof(tmp));

        while(i < s.size() && j < s.size()){

            if(reslen != -1 && j - i + 1 > reslen){

                int id2 = (int) s[i];

                if(mp[id2]){

                    if(tmp[id2] == mp[id2]){

                        sum--;

                    }

                    tmp[id2]--;

                }

                i++;

                continue;

            }

            int id = (int)s[j];

            if(mp[id]){

                tmp[id]++;

                if(tmp[id] == mp[id]){

                    sum ++;

                }

            }

            if(sum == cnt){

                if(reslen == -1 || reslen > j - i + 1){

                    resstart = i;

                    reslen = j - i + 1;

                }

                while(i < j){

                    int id2 = (int)s[i];

                    if(mp[id2]){

                        tmp[id2]--;

                        if(tmp[id2] < mp[id2]){

                            i++;

                            sum--;

                            break;

                        }

                    }

                    i++;

                    if(reslen > j - i + 1){

                        reslen = j - i + 1;

                        resstart = i;

                    }

                }

            }

            j++; 

        }

        if(reslen == -1) return "";

        return s.substr(resstart, reslen);

    }

};

/*

"ABABABABAABABAAA"

"AAA"

*/

相关文章

网友评论

      本文标题:LeetCode 76 最小覆盖子串

      本文链接:https://www.haomeiwen.com/subject/zfeuuktx.html