567. 字符串的排列
题目描述
给定字符串s1和s2,判断s2是否存在s1的子串
eg: s2:'acbdefa',s1:'db' return:true
思路分析
定长窗口移动,还是采用滑动窗口的思路去解
窗口的right指针依次向右移动,维护一个window和needs
必须是定长窗口,因此当窗口大小应当等于right-left==s1.length
当window的长度大于s1.length时就开始缩小窗口,
缩小时就判断当前的valid是否等于needs的大小,如果是则直接返回true
如果不是则更新windows的大小
代码参考
// 给定字符串s1和s2,判断s2是否存在s1的子串
// eg: s2:'acbdefa',s1:'db' return:true
const checkInclusion = function (s1, s2) {
// 创建needs以及window窗口
const needs = new Map()
const window = new Map()
for (let i of s1) {
needs.set(i, (needs.get(i) || 0) + 1)
}
let left = right = 0
let valid = 0
// right指针向右移动
while (right < s2.length) {
let c = s2[right]
right++
if (needs.has(c)) {
window.set(c, (window.get(c) || 0) + 1)
if (needs.get(c) === window.get(c)) valid++
}
// 窗口收缩条件,因为是定长窗口,也就是窗口的长度最小为s1.length
while (right - left >= s1.length) {
if (valid === needs.size) return true
let d = s2[left]
left++
if (needs.has(d)) {
if (window.get(d) === needs.get(d)) valid--
window.set(d, window.get(d) - 1)
}
}
}
return false
}
// 如果s1中不存在重复字母的话可以参考下列写法
// 采用定长窗口,一直向右移动
// const checkInclusion2 = function(s1, s2) {
// let left = 0,right = s1.length
// while(right<=s2.length){
// let str = s2.slice(left,right)
// let valid = 0
// for(let i = 0;i<s1.length;i++){
// // console.log(str,s1[i],str.includes(s1[i]),valid)
// if(str.includes(s1[i])) valid++
// if(!str.includes(s1[i])) break
// if(valid===s1.length) return true
// }
// right++,left++
// }
// return false
// };