题目
给定两个字符串 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" 的异位词。
分析
两个字符串是异位词的条件是它们包含相同的字符并且字符的频率相同。
滑动窗口法+哈希表
遍历字符串 s,每次滑动一个窗口,窗口的大小等于 p 的长度,检查窗口内的字符是否与 p 的字符频率相同。用一个哈希表记录字符串 p 中每个字符的频率,同时用另一个哈希表记录当前窗口内字符的频率。通过比较这两个哈希表,判断当前窗口是否是 p 的异位词。
时间复杂度:O(),
是字符串
s 长度
空间复杂度:O(1)
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> result;
if (s.size() < p.size()) return result;
unordered_map<char, int> pCount, windowCount;
// 初始化 p 的字符频率
for (char c : p) {
pCount[c]++;
}
// 滑动窗口
for (int i = 0; i < s.size(); i++) {
// 添加当前字符到窗口
windowCount[s[i]]++;
// 保证窗口大小与 p 相同
if (i >= p.size()) {
if (--windowCount[s[i - p.size()]] == 0) {
windowCount.erase(s[i - p.size()]);
}
}
// 如果窗口字符频率与 p 的字符频率相同,记录起始位置
if (windowCount == pCount) {
result.push_back(i - p.size() + 1);
}
}
return result;
}
};
知识充电
哈希表是无序的,因此不考虑键值对的顺序,只要两个哈希表包含相同的键值对,它们就会被认为相等。如果两个哈希表的键值对不完全一致,或者存在多余的键,那么它们就不相等。
790

被折叠的 条评论
为什么被折叠?



