首页 > 其他分享 >438. 找到字符串中所有字母异位词

438. 找到字符串中所有字母异位词

时间:2023-12-16 20:55:42浏览次数:29  
标签:count differ ++ 异位 length vector 438 字符串

1.题目介绍

给定两个字符串 \(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 * 10^{4}\)
  • \(s\) 和 \(p\) 仅包含小写字母

2.题解

2.1 滑动窗口

思路

这里便是使用滑动窗口的一种典型情形,由于窗口大小固定为p.length();
所以可以直接使用数组来存储每个字母出现次数,并通过窗口不断向后移动进行一次次判断(这里==是向量vector重载后的符号,比较每一个元素)
注意这里最后一个窗口起始值是s.length()-p.length(),而不是s.length()-p.length()-1
因为s.length() = 下标A + 1, 下标B = 下标A -(回退p.length()-1 个单位)[自身+回退的p.length()-1 = p.length()];
即下标B = 下标A - p.length() + 1 = s.length() - 1 + p.length() +1 = s.length() - p.length();

代码

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        if (s.length() < p.length()) return vector<int>();
        vector<int> ans;
        vector<int> sCount(26);
        vector<int> pCount(26);
        for (int i = 0; i < p.length(); i++){
            sCount[s[i]-'a']++;
            pCount[p[i]-'a']++;
        }
        if (sCount == pCount)  ans.push_back(0);

        for (int i = 1; i <= s.length()-p.length(); i++){
            --sCount[s[i-1] - 'a'];
            ++sCount[s[p.length()+i-1] - 'a'];
            if (sCount == pCount) ans.push_back(i);
        }
        return ans;
    }
};

复杂度分析

时间复杂度:O(m+(n−m)×Σ),其中 n 为字符串 s 的长度,m 为字符串 p 的长度,Σ 为所有可能的字符数。我们需要 O(m) 来统计字符串 p 中每种字母的数量;需要 O(m)来初始化滑动窗口;需要判断 n−m+1 个滑动窗口中每种字母的数量是否与字符串 p 中每种字母的数量相同,每次判断需要 O(Σ) 。因为 s 和 p 仅包含小写字母,所以 Σ=26。

2.2滑动窗口优化

思路

这里直接使用一个计数器 differ 来统计不同的字符数目,而不需要再遍历整个数组进行比较。

代码

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        if (s.length() < p.length()) return vector<int>();
        vector<int> ans;
        vector<int> count(26);
        for (int i = 0; i < p.length(); i++){
            count[s[i]-'a']++;  //滑动窗口中多出的字母元素个数
            count[p[i]-'a']--;  //滑动窗口中少出的字母元素个数
        }
        int differ = 0;
        for (int i = 0; i < 26; i++)
            if(count[i] != 0) differ++;
        if (differ == 0) ans.push_back(0);

        for (int i = 0; i < s.length()-p.length(); i++){
            // 首先是滑动窗口滑动排出的首个元素
            if (count[s[i]-'a'] == 1) differ--; //排出的正好是多的那个,differ--
            if (count[s[i]-'a'] == 0) differ++; //本来刚刚好,现在少了,differ++
            count[s[i] -'a']--;
            // 然后是滑动窗口滑进的新元素
            if (count[s[i+p.length()]-'a'] == -1) differ--; //新增的刚好是少一个的哪个,differ--
            if (count[s[i+p.length()]-'a'] == 0) differ++; //本来刚好,现在多一个了
            count[s[i+p.length()]-'a'] ++;
            if (differ == 0) ans.push_back(i+1);
        }
        return ans;
    }
};

复杂度分析

时间复杂度:O(n+m+Σ),其中 n 为字符串 s 的长度,m 为字符串 p 的长度,其中 Σ 为所有可能的字符数。我们需要 O(m)来统计字符串 p 中每种字母的数量;需要 O(m) 来初始化滑动窗口;需要 O(Σ) 来初始化 differ;需要 O(n−m) 来滑动窗口并判断窗口内每种字母的数量是否与字符串 p 中每种字母的数量相同,每次判断需要 O(1) 。因为 s 和 p 仅包含小写字母,所以 Σ=26。

标签:count,differ,++,异位,length,vector,438,字符串
From: https://www.cnblogs.com/trmbh12/p/17908356.html

相关文章

  • 浙江集训字符串专题
    \(\text{CF1207G}\)题目描述有\(n\)次操作,每一次操作描述了第\(i\)个字符串,要么是单独一个字符,要是是在第\(j\)个字符串后拼接一个字符得到。接下来又\(m\)次询问,每一次给出一个字符串问在第\(i\)个字符串中出现了多少次?思路考虑检出\(\text{ACAM}\)。一个字符串......
  • Java 字符串、数组、ArrayList转换
    Java字符串、数组、ArrayList之间的相互转换 数组转字符串importjava.util.Arrays;publicclassTest02{publicstaticvoidmain(String[]args){int[]scores1=newint[]{10,20,30,40,50};int[]scores2={10,20,30,40,50};//数......
  • string.replace()与removeprefix() 和 removesuffix()的区别 字符串技巧
    string.replace(),removeprefix()和removesuffix()是Python中的字符串方法,它们都用于修改字符串,但是它们的功能和使用方式有所不同:string.replace(old,new[,count]):这个方法会将字符串中的old子串替换为new子串。如果提供了可选参数count,则只替换前count个old子串¹......
  • 字符串基础
    字符串常用操作定义字符串时,单引号,双引号,三引号都可以 字符串拼接#字符串拼接s1='i's2='love's3='you's4=s1+''+s2+''+s3print(s4)s4=f'{s1}{s2}{s3}'print(s4)字符串切片对于字符串里的每个字符都有特定的位置索引s='testfan'从上......
  • 哈希表(HashMap)与字符串哈希
    哈希表哈希表是一种通过映射来快速查找的数据结构。其通过键值对(key-value)来存储。一个数据通过哈希函数的运算来生成一个属于他自己的键值,尔后将其与键值绑定。当我们想查找这个数据时,就可以直接通过键来访问对应的值,时间复杂度近似为O(1)。哈希表适用于这样一种场景,当数据......
  • 解决方案 | pywintypes.com_error: (-2147221005, '无效的类字符串', None, None) --P
     1背景importpythoncomimportwin32com.clientimportmathwincad=win32com.client.Dispatch("AutoCAD.Application")#强制打开cad,该句发生报错信息doc=wincad.ActiveDocumentdoc.Utility.Prompt("Hello!Autocadfrompywin32com.\n")msp=doc.Mode......
  • 【kmp算法】字符串匹配
    一,解决问题kmp算法解决的是字符串匹配的问题,具体来说假定我们要在主串s[]中匹配模式串p[],找到匹配到的位置loc;二,具体实现和演变过程最自然的想法是暴力写法(BF)枚举主串字符s[i],和模式串p[j]。一个一个匹配,如果匹配失败,i指针回退回起点,往前进一位,再次进行比较,......
  • C#根据类的Name字符串找到类
    C#中根据类的名称字符串创建类的实例这种⽤法很像是⼯⼚类,但是我们不需要⾃⼰实现字符串到类型的对应关系,也不需要创建的类有继承关系,代码如下://第⼀步:得到类的全名(命名空间+类名)stringadaptorName=namespace+classname;//第⼆部:根据全名得到类的类型TypeadaptorType......
  • Access数据库的中长字符串字段
    CREATETABLEoauth2_registered_client(idvarchar(36)NOTNULL,client_idvarchar(64)NOTNULL,client_id_issued_attimestampNOTNULL,client_secretvarchar(255)NULL,client_secret_expires_attimestampNULL,client_namevarchar......
  • shell补-特殊玩法-生成随机字符串
    shell补-特殊玩法-生成随机字符串方法1:md5sum方法2:tr+/dev/urandom方法3:内置变量RANDOM;#方法1[root@localhostser]#opensslrand-base64108/54arQpCmQ12Q==[root@localhostser]##方法2必备[root@localhostser]#date+%N|md5sum###给日期加密;可以写其......