思路分析:
- 通过两个数组
hash1
和hash2
分别记录字符串s1
和当前窗口内的s2
中各个字符的出现次数。 - 初始化时,遍历前
n
个字符,更新hash1
和hash2
。 - 在遍历过程中,通过滑动窗口的方式,不断更新
hash2
,并检查是否存在与hash1
相等的子串。 - 如果找到相等的子串,则返回
true
,否则继续遍历直至结束。
class Solution {
public:
bool checkInclusion(string s1, string s2) {
// 初始化两个大小为26的数组,分别用于存储字符串s1和s2中各个字符的出现次数
vector<int> hash1(26, 0);
vector<int> hash2(26, 0);
int i;
int n = s1.size(); // 获取字符串s1的长度
int m = s2.size(); // 获取字符串s2的长度
// 如果s2的长度小于s1的长度,则s2不可能包含s1的任意排列,直接返回false
if (m < n)
return false;
// 初始化hash1和hash2数组,分别记录s1和s2中前n个字符的出现次数
for (i = 0; i < n; i++) {
hash1[s1[i] - 'a']++;
hash2[s2[i] - 'a']++;
}
// 对hash2中最后一个字符的出现次数减一,方便后续将移动窗口
hash2[s2[n - 1] - 'a']--;
// 遍历s2中的每个字符,检查是否存在包含s1排列的子串
for (i = 0; i <= m - n; i++) {
// 更新hash2数组
hash2[s2[i + n - 1] - 'a']++;
// 检查hash1和hash2是否相等,即检查s2中当前窗口是否包含s1的排列
if (hash1 == hash2)
return true;
else
// 如果不相等,将窗口右移,更新hash2数组
hash2[s2[i] - 'a']--;
}
// 如果遍历完整个s2都没有找到包含s1排列的子串,返回false
return false;
}
};