题目链接
https://leetcode.com/problems/find-all-anagrams-in-a-string/description/
https://leetcode.com/problems/permutation-in-string/description/
题意
给定两个字符串s和p,求s的子串所有的起点,满足这些子串是p的anagrams(字符的频率相同,但是可能顺序不同)
题解
定长滑动窗口,统计窗口内的字符是否是p的anagrams
Leetcode 438
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
unordered_map<char, int> mp1;
unordered_map<char, int> mp2;
vector<int> ret;
int l = 0;
int r = 0;
int valid = 0;
for(char ch: p) {
mp1[ch]++;
}
while( r < s.size()) {
char ch = s[r];
if(mp1.count(ch)) {
mp2[ch]++;
if(mp1[ch] == mp2[ch]) {
valid++;
}
}
r++;
while(r - l >= p.size()) {
if(valid == mp1.size()) {
ret.push_back(l);
}
char ch = s[l];
l++;
if(mp1.count(ch)) {
if(mp1[ch] == mp2[ch]) {
valid--;
}
mp2[ch]--;
}
}
}
return ret;
}
};
容易错的点:
- 定长滑动窗口的模版中,由于在缩小窗口之前r++,那么这是一个左闭右开的区间,r - l 就是窗口的大小
- 比较窗口中的字符串和字符串p的时候,valid–的条件是他们两个对应的hashset的值相等
时间复杂度:O(n) n 为s的长度
空间复杂度:O(m) m为p的长度
Leetcode 567
class Solution {
public:
bool checkInclusion(string s1, string s2) {
unordered_map<char, int> mp1;
unordered_map<char, int> mp2;
int valid = 0;
for(char ch: s1) {
mp1[ch]++;
}
int l = 0;
int r = 0;
while(r < s2.size()) {
char ch = s2[r];
if(mp1.count(ch)) {
mp2[ch]++;
if(mp1[ch] == mp2[ch]) {
valid++;
}
}
r++;
while( r - l >= s1.size()) {
if(valid == mp1.size()) {
return true;
}
char ch = s2[l];
l++;
if(mp1.count(ch)) {
if(mp1[ch] == mp2[ch]) {
valid--;
}
mp2[ch]--;
}
}
}
return false;
}
};