题目
Given two strings s1 and s2, write a function to return true if s2 contains the permutation of s1. In other words, one of the first string’s permutations is the substring of the second string.
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
Note:
- The input strings only contain lower case letters.
- The length of both given strings is in range [1, 10,000].
解题思路
建立一个记录所有字母出现次数的哈希表 origin
,初始化时扫描 s1
的所有字母,对于遇到的每个字母 c
执行 origin[c]++
记录出现次数,同时扫描 s2
的前 s1.length()
个字母,对于遇到的每个字母 d
执行origin[d]--
进行相消操作,相消完成后判断 origin
中每个字母的出现次数是否都变为 0
,若是,则 return true
,否则,继续进行后面的移动窗口操作。
以字符串 s1
的长度创建一个移动窗口,以这个移动窗口去扫描 s2
,每次移动一个字母的位置,当有一个字母 c
被移出了窗口,则其对应的哈希值 origin[c]++
,当有一个字母 d
进入了窗口,则其对应的哈希值 origin[d]--
,这样一直扫描直到遍历完 s2
的所有字母,在这个过程中如果当窗口移动到某一个位置时,origin
中所有字母的出现次数都变为0,则 return true
;当遍历完成还没有返回,则 return false
。
C++代码实现
class Solution {
public:
bool checkInclusion(string s1, string s2) {
if (s1.length() > s2.length() || s2 == "") { return false; }
unordered_map<char, int> origin;
for (int i = 0; i < s1.length(); ++i) {
origin[s1[i]]++;
origin[s2[i]]--;
}
if (allZero(origin)) { return true; }
for (int i = s1.length(); i < s2.length(); ++i) {
origin[s2[i - s1.length()]]++;
origin[s2[i]]--;
if (allZero(origin)) { return true; }
}
return false;
}
bool allZero(unordered_map<char, int>& origin) {
for (char i = 'a'; i <= 'z'; ++i) {
if (origin[i] != 0) { return false; }
}
return true;
}
};