题目:
Given two strings s1
and s2
, return true if s2
contains the permutation of s1
.
In other words, one of s1
's permutations is the substring of s2
.
Example 1:
Input: s1 = "ab", s2 = "eidbaooo" Output: true Explanation: s2 contains one permutation of s1 ("ba").
Example 2:
Input: s1 = "ab", s2 = "eidboaoo" Output: false
Constraints:
1 <= s1.length, s2.length <= 104
s1
ands2
consist of lowercase English letters.
思路1:
这里用滑动窗口做,常规做法是两个哈希map,need存入需要的字符串,cur代表当前窗口的字符串。首先右端右移,如果需要当前字符,记录更新当前窗口。如果当前字符在窗口中的信息和need中相同,使valid加1,当valid与need的size相同时,我们确认true即可。然后是左端口右移并且更新窗口内数据,与前面对称的,如果当前字符在need中,则valid需要减1。最后如果循环结束未找到则返回false。
代码1:
class Solution {
public:
bool checkInclusion(string s1, string s2) {
unordered_map<char, int> need, cur;
for(auto c:s1)
need[c]++;
int left=0, right=0, valid=0;
while(right<s2.size()){
char c=s2[right];
right++;
if(need.count(c)){
cur[c]++;
if(cur[c]==need[c])
valid++;
}
while(right-left>=s1.size()){
if(valid==need.size())
return true;
char d=s2[left];
left++;
if(need.count(d)){
if(need[d]==cur[d])
valid--;
cur[d]--;
}
}
}
return false;
}
};
思路2:
其实也是滑动窗口的方法但是用了两个vector替代并且运行速度是要高于方法一的。首先是用大小为26的vector来记录s1中的字母频数。然后滑动窗口,每次如果当前窗口长度已经超过s1的长度,则右移左端口,然后右移右端口,这里其实是每次都移动一格,即端口向前移一步,每次移动结束后,判断两个记录的vector是否相同,如果相同则返回true。
代码2:
class Solution {
public:
bool checkInclusion(string s1, string s2) {
if(s1.size()>s2.size())
return false;
int n= s1.size();
int m=s2.size();
vector<int> v1(26);
for(auto i:s1)
v1[i-'a']++;
vector<int> v2(26);
for(int i=0;i<m;i++)
{
if(i>=n)
v2[s2[i-n]-'a']--;
v2[s2[i]-'a']++;
if(v1==v2)
return true;
}
return false;
}
};