题目分析
给定两个字符串 s 和 p,找出 s 中所有是 p 异位词的子串起始索引。
异位词是指字符串字符组成相同但顺序不同的字符串。
思路
-
异位词的定义是字符频次相同,所以我们需要判断子串字符频次是否和
p相同。 -
用一个大小为 26 的数组统计
p中字符频次,另一个数组动态维护滑动窗口中字符频次。 -
使用滑动窗口,窗口大小固定为
p的长度。 -
窗口每右移一次:
- 新字符频次加 1
- 窗口超过长度时,移除左边字符频次
-
每次窗口大小等于
p长度时,比较两个频次数组,相等则说明找到一个异位词。
代码
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> sCnt(26, 0), pCnt(26, 0);
vector<int> ans;
int n = s.size(), m = p.size();
if (n < m) return ans;
// 统计p中字符频次
for (char c : p) {
pCnt[c - 'a']++;
}
int l = 0;
for (int r = 0; r < n; ++r) {
sCnt[s[r] - 'a']++;
// 窗口超过p长度时,左边字符频次减一,左指针右移
if (r - l + 1 > m) {
sCnt[s[l] - 'a']--;
l++;
}
// 窗口大小等于p长度时比较频次数组
if (r - l + 1 == m && sCnt == pCnt) {
ans.push_back(l);
}
}
return ans;
}
};
复杂度分析
- 时间复杂度:
O
(
n
)
O(n)
O(n),遍历
s一次,频次数组比较为 O ( 26 ) O(26) O(26) 视为常数。 - 空间复杂度: O ( 1 ) O(1) O(1),使用固定大小频次数组。
定长滑动窗口模板
void fixedLengthSlidingWindow(const vector<int>& arr, int k) {
int n = arr.size();
if (k > n) return;
// 这里可以存一些窗口内的信息,比如窗口和、频率、最大值等
int window_sum = 0;
// 先处理第一个窗口
for (int i = 0; i < k; ++i) {
window_sum += arr[i];
}
cout << "Window [0, " << k - 1 << "] sum = " << window_sum << "\n";
// 滑动窗口开始移动
for (int i = k; i < n; ++i) {
window_sum -= arr[i - k]; // 去掉左边的元素
window_sum += arr[i]; // 加入右边的元素
cout << "Window [" << i - k + 1 << ", " << i << "] sum = " << window_sum << "\n";
}
}
984

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



