题目
链接:https://leetcode.cn/problems/MPnaiL/
给定两个字符串 s1
和 s2
,写一个函数来判断 s2
是否包含 s1
的某个变位词。
换句话说,第一个字符串的排列之一是第二个字符串的 子串 。
思路
题目描述的有些不清晰,我理解的是:第一个字符串中的全部字符任意排列,能形成第二个字符串中的子串。
那我们要满足的条件就是:
- s2中符合条件的子串长度等于s1的长度
- s2中这个子串的每个小写字母出现的个数,等于s1中每个小写字母出现的次数
连续的子串,让我们容易想到双指针。而统计小写字母的个数,又是我们熟悉的,可以用长度26位的数组(哈希表),保存每一个字母出现的个数。
解法:双指针+哈希表
逻辑
- 用一个长度26位的数组保存每个小写字母出现的次数
- 遍历s1,填充数组
- 双指针处理s2,先从0开始,将右指针向右移动到s1.length-1的位置。每次移动时,看当前下标的字母,并在数组中对应的位置减1。
- 双指针同时向右移动。左指针移出的字母,在数组对应的位置加1,右指针移入的字母,在数组对应的位置减1。每次移动都统计数组中是否均为0,是则返回true。
代码
public boolean checkInclusion(String s1, String s2) {
if (s1.length() > s2.length()) {
return false;
}
int[] counts = new int[26];
for (int i = 0; i < s1.length(); i++) {
counts[s1.charAt(i) - 'a'] += 1;
counts[s2.charAt(i) - 'a'] -= 1;
}
if (allZero(counts)) {
return true;
}
for (int i = s1.length(); i < s2.length(); i++) {
counts[s2.charAt(i) - 'a'] -= 1;
counts[s2.charAt(i-s1.length()) - 'a'] += 1;
if (allZero(counts)) {
return true;
}
}
return false;
}
public boolean allZero(int[] counts){
for (int count : counts) {
if (count != 0) {
return false;
}
}
return true;
}