1. 题目链接:438. 找到字符串中所有字母异位词
2. 题目描述:
给定两个字符串
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
仅包含小写字母
3. 解法(滑动窗口+哈希表)
3.1 算法思路:
- 因为字符串p的异位词的长度一定与字符串p的长度相同,所以我们可以在字符串
s
中构造一个长度为与字符串p
的长度相同的滑动窗口,并在滑动中维护窗口中每种字母的数量 - 当窗口中每种字母的数量与字符串p中每种字母的数量相同时,则说明当前窗口为字符串
p
的异位词 - 因此可以用两个大小为
26
的数组来模拟哈希表,一个来保存s
中的子串每个字符出现的个数, - 另一个来保存
p
每一个字符出现的个数。这样就能判断两个串是否是异位词
3.2 算法流程:
- 初始化
hash1
数组,用来统计字符串p中每个字符出现的次数。 - 初始化
hash2
数组,用来统计滑动窗口内每个字符出现的次数。 - 将滑动窗口的左边界
left
和右边界right
都初始化为0
。 - 遍历字符串
s
,从左到右依次将字符加入窗口。 - 判断是否需要移动窗口。如果窗口长度超过了
p
的长度,就需要移动窗口,判断是否需要从窗口中移出最左边的字符。 - 如果需要移出字符,就从窗口中移出最左边的字符,并更新
hash2
数组和count
变量。 - 判断窗口内的字符是否是
p
的异位词。如果是,将左边界的索引加入结果数组ret
。 - 返回结果数组
ret
。
3.3 C++算法代码:
class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int> ret;int hash1[26]={0};//统计字符串p中每个字符出现的次数for(auto ch:p)hash1[ch-'a']++;int hash2[26]={0};//统计窗口里面的每个字符出现的个数int m=p.size();for(int left=0,right=0,count=0;right<s.size();right++){char in=s[right];if(++hash2[in-'a']<=hash1[in-'a'])count++;//进窗口+维护countif(right-left+1>m)//判断{char out=s[left++];if(hash2[out-'a']--<=hash1[out-'a'])count--;//出窗口+维护 count}//更新结果if(count==m)ret.push_back(left); }return ret;}
};