LeetCode上字符串的排列,中等难度的,记录下解题思路
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列,s1的排列不限,只要s2中包含s1的任意排序数组即可
那么就是给定个s1长度的窗口,在s2中移动,每次移动都判断当前窗口中的数组和s1的关系
反正只需要判断窗口内是否有s1的元素即可
- 通过遍历s1,建立一个关于s1的map,对应s1的元素和出现的次数
- 在s2上创建窗口,窗口也创建一个对应的map,用于记录当前窗口内的元素和出现的次数
- 当窗口大小等于s1的长度的时候,对比当前窗口map以及s1的map之间是否相等
如果相等,那就代表窗口的元素和出现的次数就和s1相同,那么就满足题意 - 窗口大于s1长度的时候,那么窗口就要整体右移,将窗口left对应的元素移出,并且修改map中对应元素出现的次数
- 如果循环完整个s2还没有出现窗口和s1相等的情况,那么就代表整个s2都不满足条件,返回false
var checkInclusion = function(s1, s2) {
// 传入的是s1和s2两个字符串,保存对应的长度
let s1_len = s1.length
let s2_len = s2.length
// 用Map保存s1中出现的元素次数
let s1_map = new Map()
// 另一个map保存窗口中的元素
let s2_map = new Map()
// 定义窗口
let left = 0
let right = 0
// 首先遍历s1,创建map
for(let i =0;i<s1_len;i++) {
if(!s1_map.has(s1[i])) {
// 如果没有这个元素
s1_map.set(s1[i],1)
} else {
// 如果有这个元素
s1_map.set(s1[i],s1_map.get(s1[i])+1)
}
}
// console.log(s1_map);
// 使用窗口遍历s2
while(right < s2_len) {
// 当窗口右边没有到达最右侧的时候
if(!s2_map.has(s2[right])) {
// 如果s2_map中不存在这个元素就添加
s2_map.set(s2[right],1)
} else {
// 存在就+1
s2_map.set(s2[right],s2_map.get(s2[right])+1)
}
// console.log(s2_map);
if(right - left + 1 === s1_len) {
// 计数位
let count = 0
// 如果当前窗口大小正好等于s1的时候
s1_map.forEach((x,i) => {
// 遍历s1_map 判断当前窗口内是否有这些元素,并且相等
// console.log(s2_map.has(i),s2_map.get(i),i,x);
if(s2_map.has(i) && s2_map.get(i) === x) {
count = count + x
}
})
// console.log(count,s1_len);
if(count === s1_len) return true
}
right++
if(right - left + 1 > s1_len) {
// 当窗口大于s1的长度的时候
//要将left元素移出
s2_map.set(s2[left],s2_map.get(s2[left])-1)
//left还要右移
left++
}
}
return false
};