力扣刷题HOT100——438.找到字符串中所有字母异位词
给定两个字符串 s
和 p
,找到 s
中所有 p
的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
示例 1:
输入: s = "cbaebabacd", p = "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。 起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
思路:
滑动窗口。
- 界条件检查:在函数开始时,检查
s
的长度是否小于p
的长度,若小于则直接返回空结果。 - 字符计数统计:分别统计字符串
p
中每个字符的出现次数到pmp
中,以及初始窗口内字符的出现次数到smp
中。 - 检查初始窗口:比较
smp
和pmp
,若相等则将起始索引 0 添加到结果中。 - 移动滑动窗口:
i
从plen
开始,每次移动窗口时,移除窗口最左边的字符,添加窗口最右边的字符,并更新smp
。若更新后的smp
和pmp
相等,则将当前窗口的起始索引添加到结果中。
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> res;
int slen=s.size();
int plen=p.size();
unordered_map<char,int> pmp;
for(char x:p)
{
pmp[x]++;
}
unordered_map<char,int> smp;
// 初始化滑动窗口
for (int i = 0; i < plen; i++) {
smp[s[i]]++;
}
// 检查初始窗口是否是 p 的字母异位词
if (smp == pmp) {
res.push_back(0);
}
for(int i=plen;i<slen;i++)
{
smp[s[i - plen]]--;
if (smp[s[i - plen]] == 0) {
smp.erase(s[i - plen]);
}
smp[s[i]]++;
if(smp==pmp)
{
res.push_back(i-plen+1);
}
}
return res;
}
};
复杂度分析
- 时间复杂度:\(O(n)\),其中 n 是字符串
s
的长度。每个字符最多被访问两次。 - 空间复杂度:\(O(k)\),其中 k 是字符集的大小,主要用于存储
pmp
和smp
。