简介
题目链接:https://leetcode.cn/problems/permutation-in-string/description/
解决方式:字符串 + 滑动窗口(双指针)、哈希表
这是作者学习众多大神的思路进行解题的步骤,很推荐大家解题的时候去看看题解里面大佬们的思路、想法!
滑动窗口
思路:这题的思路与76.最小覆盖子串题目类似,都是使用滑动窗口然后通过哈希表或数组第三方数据结构判断滑动窗口的扩大、收缩时机。不一样的是,收缩条件变为滑动窗口的长度等于目标的长度。在这种情况下,valid 变量等于所需字符种类数,相当于固定长度(长度等于目标)的滑动窗口包含了所有目标字符种类且满足数量,该窗口字串就是目标的排列了。
哈希表
java
class Solution {
public boolean checkInclusion(String s1, String s2) {
// 哈希表,需要的字符种类和数量
HashMap<Character,Integer> need = new HashMap();
for(char c : s1.toCharArray()){
need.put(c, need.getOrDefault(c, 0) + 1);
}
// 哈希表,滑动窗口中存在的目标字符种类和数量
HashMap<Character,Integer> window = new HashMap();
// 滑动窗口是否满足目标种类数
int valid = 0;
// 双指针
int left = 0;
int right = 0;
// 迭代
while(right < s2.length()){ // 注意,right 是开区间,即左闭右开
// 当前元素
char c = s2.charAt(right);
// 滑动窗口扩大
right++;
//当前元素判断
if(need.containsKey(c)){
// 当前元素是目标之一,存放进 window 中
window.put(c, window.getOrDefault(c, 0) + 1);
// 判断当前元素是否数量满足
if(window.get(c).equals(need.get(c))){
// 满足,则 valid + 1,表明 window 中该字符种类数量满足目标
valid++;
}
}
// 同步进行缩小判断
while(right - left == s1.length()){
// 左闭右开,right - left 即滑动窗口长度等于 s1
// 长度相等时,判断是否是排列之一
if(valid == need.size()){
// 长度相同,字符种类和数量又满足,说明是排列之一
return true;
}
// 否则不是排列,虽然长度相同但是有别的字符,需去除其他字符重新查找
char cleft = s2.charAt(left);
left++;
// 判断是否是目标字符之一
if(need.containsKey(cleft)){
// 是,则需判断移除该元素之前,数量是否等于目标数量,是则需修改valid
if(window.get(cleft).equals(need.get(cleft))){
// 因为移除后数量不满足了
valid--;
}
window.put(cleft, window.getOrDefault(cleft, 0) - 1);
}
}
}
// 迭代退出,说明没有结果
return false;
}
}