题目
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的某个变位词。
换句话说,第一个字符串的排列之一是第二个字符串的 子串
- 输入与输出
输入: s1 = “ab” s2 = “eidbaooo”
输出: True
解释: s2 包含 s1 的排列之一 (“ba”).
思路
题目求的是 s2 中是否包含 s1 (s1 可以自由组合),于是我想到了
- s2 求全排列;
- 嵌套循环,把 s1 可能的子串全部列举出来,
- 看 s2 的排列中是否存在 s1 的子串。
毫无意外,超时了,很惨
毫无意外,超时了,很惨
毫无意外,超时了,很惨
于是。。。都不好意思说了,又去看题解(大佬题解)。还是滑动窗口的问题,为什么总是想不到呢?
- 把 s1 用哈希表保存起来;
- 将 s1 大小相同的作为滑动窗口起点,像右边滑动;
- 如果中途窗口值和 s1 相等,那么就返回 true,否则返回 false。
- 至于 s1 为什么用 哈希表 保存呢?
s1 可以任意排列组合,所以它的顺序也就无关紧要了!- 而 窗口值 也用 哈希表 保存?
是的,没错,只要 窗口值 的字母以及出现的次数和 s1 相等,那么 窗口值 想要的排列 s1 都能给整出来。(哥哥想要的我都会。。。。)
图解如下:

代码
class Solution {
public boolean checkInclusion(String s1, String s2) {
// 如果 s1 长度大于 s2, 那么肯定不可以
if (s1.length() > s2.length()) {
return false;
}
// 自制哈希表, 好用没烦恼
int[] letters1 = new int[26];
int[] letters2 = new int[26];
for (int i = 0; i < s1.length(); i++) {
letters1[s1.charAt(i)-'a']++;
letters2[s2.charAt(i)-'a']++;
}
// 如果 s1 和 s2 相等, 那么返回 true
if (Arrays.equals(letters1,letters2)) {
return true;
}
// 定义窗口大小初始值
int left = 0;
int right = s1.length();
// 滑起来
while (right < s2.length()) {
// 记得更改窗口左边界限
// 例如上图中 'd' 比较完了, 那么 窗口中的值就不应该有
// 但是 'd' 可能不止一个
letters2[s2.charAt(left)-'a']--;
letters2[s2.charAt(right)-'a']++;
// 相等返回 true
if (Arrays.equals(letters1,letters2)) {
return true;
}
// 窗口移动
right++;
left++;
}
// 结束都没有, 那么返回 false
return false;
}
}
吐槽一下,为什么我总是想不出来啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
浙公网安备 33010602011771号