567. 字符串的排列
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。
示例1:
输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").
示例2:
输入: s1= "ab" s2 = "eidboaoo"
输出: False
注意:
输入的字符串只包含小写字母
两个字符串的长度都在 [1, 10,000] 之间
解题思路
字符串b是否是字符串a的排列之一的判断条件是:字符串a和b中出现的字符相同,且出现次数相等
1. c++ next_permutation
- sort + next_permutation + find超时
- sort + next_permutation + kmp超时
2. 滑动窗口
class Solution {
public:
//滑动窗口
//mp[c] 正数 0 负数
bool checkInclusion(string s1, string s2) {
if(s1.length()>s2.length())
return false;
unordered_map<char,int> mp;
for(auto c : s1){
mp[c]++;
}
int len1 = s1.length();
int len2 = s2.length();
int left = 0;
int right = 0;
while(right<len2){
char c = s2[right++];
mp[c]--;//right进入窗口
while(left<right && mp[c]<0){//left移动至mp[c]>=0处,新窗口从该处开始
mp[s2[left]]++;//恢复
++left;
}
if(right-left==len1){
return true;
}
}
return false;
}
};
3. 数组
class Solution {
public:
bool isEqual(vector<int> a, vector<int> b){
//cout <<a.size()<<" "<<b.size()<<"\n";
for(int i=0; i<a.size()&&i<b.size(); ++i){
if(a[i]!=b[i])
return false;
}
return true;
}
bool checkInclusion(string s1, string s2) {
if(s1.size()>s2.size())
return false;
vector<int> cnt1(26,0);
vector<int> cnt2(26,0);
for(auto c : s1){
cnt1[c-'a']++;
}
int len1 = s1.size();
int len2 = s2.size();
for(int i=0; i<=len2-len1; ++i){
for(int j=0; j<len1; ++j){
char c = s2[i+j];
cnt2[c-'a']++;
}
if(isEqual(cnt1,cnt2)){
return true;
}
else {
cnt2.clear();
cnt2.resize(26);//*
}
}
return false;
}
};