题目链接
tag:
- Medium;
- Sliding Window;
question
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].
思路:
本题给了两个字符串s1和s2,问我们s1的全排列的字符串任意一个是否为s2的字串。虽然题目中有全排列的关键字,但是跟之前的全排列的题目的解法并不一样,如果遍历s1所有全排列的情况,然后检测其是否为s2的子串,非常不高效的,最大10000的阶乘,估计会超时。
正确做法应该是使用滑动窗口 Sliding Window
的思想来做,可以使用两个哈希表来做,先分别统计s1和s2中前n1个字符串中各个字符出现的次数,其中n1为字符串s1的长度,这样如果二者字符出现次数的情况完全相同,说明s1和s2中前n1的字符互为全排列关系,那么符合题意了,直接返回true。如果不是的话,那么我们遍历s2之后的字符,对于遍历到的字符,对应的次数加1,由于窗口的大小限定为了n1,所以每在窗口右侧加一个新字符的同时就要在窗口左侧去掉一个字符,每次都比较一下两个哈希表的情况,如果相等,说明存在,代码如下:
class Solution {
public:
bool checkInclusion(string s1, string s2) {
// 一定要做特殊处理
if (s1.size() > s2.size())
return false;
if (s1.size() == 0)
return true;
if (s2.size()==0)
return false;
int n1 = s1.size(), n2 = s2.size();
// 双哈希
vector<int> m1(128), m2(128);
for (int i = 0; i < n1; ++i) {
++m1[s1[i]];
++m2[s2[i]];
}
if (m1 == m2)
return true;
for (int i = n1; i < n2; ++i) {
++m2[s2[i]];
--m2[s2[i - n1]];
if (m1 == m2)
return true;
}
return false;
}
};