【力扣刷题】438. 找到字符串中所有字母异位词-滑动窗口

给定两个字符串 s 和 p,找到 s 中所有 p 的  的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

 

示例 1:

输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

 示例 2:

输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

 

提示:

  • 1 <= s.length, p.length <= 3 * 104
  • s 和 p 仅包含小写字母

思路1:
因为字符串 p 的异位词的长度一定与字符串 p 的长度相同,所以我们可以在字符串 s 中构造一个长度为与字符串 p 的长度相同的滑动窗口,并在滑动中维护窗口中每种字母的数量;当窗口中每种字母的数量与字符串 p 中每种字母的数量相同时,则说明当前窗口为字符串 p 的异位词。

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        int n=s.size(),m=p.size();
        cout<<n<<" "<<m<<endl;
        if(m>n)return vector<int>();
        vector<int>ans;
        vector<int>scnt(26);
        vector<int>pcnt(26);
        for(int i=0;i<m;i++){
            ++scnt[s[i]-'a'];
            ++pcnt[p[i]-'a'];
        }
        if(scnt==pcnt){
            ans.push_back(0);
        }
        for(int i=0;i<n-m;i++){
            --scnt[s[i]-'a'];
            ++scnt[s[i+m]-'a'];
            if(scnt==pcnt){
                ans.push_back(i+1);
            }
        }
        return ans;
    }
};

 

思路2:优化的滑动窗口
在方法一的基础上,我们不再分别统计滑动窗口和字符串 p 中每种字母的数量,而是统计滑动窗口和字符串 p 中每种字母数量的差;并引入变量 differ 来记录当前窗口与字符串 p 中数量不同的字母的个数,并在滑动窗口的过程中维护它。

在判断滑动窗口中每种字母的数量与字符串 p 中每种字母的数量是否相同时,只需要判断 differ 是否为零即可。

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        int n=s.size(),m=p.size();
        cout<<n<<" "<<m<<endl;
        if(m>n)return vector<int>();
        vector<int>ans;
        vector<int>cnt(26);
        for(int i=0;i<m;i++){
            ++cnt[s[i]-'a'];
            --cnt[p[i]-'a'];
        }
        int diff=0;
        for(int j=0;j<26;j++){
            if(cnt[j]!=0){
                diff++;
            }
        }
        if(diff==0){
            ans.push_back(0);
        }
        for(int i=0;i<n-m;i++){
            if(cnt[s[i]-'a']==1){
                diff--;
            }else if(cnt[s[i]-'a']==0){
                diff++;
            }
            --cnt[s[i]-'a'];

            if(cnt[s[i+m]-'a']==-1){
                diff--;
            }else if(cnt[s[i+m]-'a']==0){
                diff++;
            }
            cnt[s[i+m]-'a']++;
            if(diff==0){
                ans.push_back(i+1);
            }
        }
        return ans;
    }
};

 

版权声明:
作者:Zhang, Hongxing
链接:http://zhx.info/archives/572
来源:张鸿兴的学习历程
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录