Problem: 438. 找到字符串中所有字母异位词
438. 找到字符串中所有字母异位词
- 预备知识
- 解题思路
- 复杂度
- Code
- 其它细节
- 推荐博客或题目
- 博客
- 题目
- 滑动窗口
- 哈希表
预备知识
此题用到了双指针算法中的滑动窗口思想,以及哈希表的运用。c++中是unordered_map。如果对此不了解的uu,建议查看相关介绍博客和更简单的题目!!!
解题思路
该题解法为:滑动窗口 + 哈希表。
-
该题的滑动窗口是固定的,我们只需要对每次移动新字符和删除字符进行判断,时间复杂度为O(n)。
-
首先,定义一个哈希表,记录要满足匹配p字符串需要多少的对应的字符。
unordered_map<char, int> pp;
-
遍历p,出现对应的字符,就在该位置的–,说明还需要在s中找多少该字符。
while (j < p.size()) { //O(1) 理论上子字符串的操作应该是1 //开始遍历,在s上初始化第一个字符串,能够满足对应字符供给的就++ pp[s[j++]]++; }
-
遍历pp,如果不为0,说明该子字符串不满足匹配条件,则跳到x.
for (auto& [a, b] : pp) { //O(1) max=26 //遍历pp,如果不为0,说明该子字符串不满足匹配条件,则跳到x if (b != 0) goto x; }
-
最后进行全局遍历
while (j < s.size()) { //O(n) //开始遍历 //对于j位置的字符,将pp对应位置++,表示提供一个字符 pp[s[j]]++; //对于i位置的字符,将pp对应位置--,表示不能提供一个字符 pp[s[i]]--; for (auto& [a, b] : pp) { //O(1) max=26 if (b != 0) goto xx; } v.push_back(i + 1); xx:; i++;j++; }
复杂度
时间复杂度:
O(26 * n),26是遍历哈希表中的每种英文字母的个数,最多为26,n是遍历滑动窗口。
空间复杂度:
O(26 + n),26是哈希表最大size,n是vector最大size。
Code
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
//记录要满足匹配p字符串需要多少的对应的字符
unordered_map<char, int> pp;
vector<int> v;
int i = 0, j = 0;
for (auto a : p) { //O(n)
//遍历p,出现对应的字符,就在该位置的--,说明还需要多少该字符
pp[a]--;
}
while (j < p.size()) { //O(1) 理论上子字符串的操作应该是1
//开始遍历,在s上初始化第一个字符串,能够满足对应字符供给的就++
pp[s[j++]]++;
}
for (auto& [a, b] : pp) {
//调试bug的时候可以用输出的方法
cout << a << b << endl;
}
for (auto& [a, b] : pp) { //O(1) max=26
//遍历pp,如果不为0,说明该子字符串不满足匹配条件,则跳到x
if (b != 0) goto x;
}
v.push_back(i);
x:;
while (j < s.size()) { //O(n)
//开始遍历
//对于j位置的字符,将pp对应位置++,表示提供一个字符
pp[s[j]]++;
//对于i位置的字符,将pp对应位置--,表示不能提供一个字符
pp[s[i]]--;
for (auto& [a, b] : pp) { //O(1) max=26
if (b != 0) goto xx;
}
v.push_back(i + 1);
xx:;
i++;j++;
}
return v;
}
};
其它细节
可以尝试用输出日志的方式来获得局部代码的正确性。对于比较长的代码,我们应该在写完整个代码之前,已经完成多个地方的日志输出。多加练习能够提高自己写代码的正确性。
for (auto& [a, b] : pp) {
//调试bug的时候可以用输出的方法
cout << a << b << endl;
}
推荐博客或题目
博客
- 滑动窗口详解
- 哈希表理论基础
题目
滑动窗口
- 无重复字符的最长子串 难度:++
哈希表
- 两数之和 难度:++
- 三数之和 难度:+++
- 四数之和 难度:++++
- 四数相和II 难度:++++