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
// };
posted @ 2023-03-18 00:36  含若飞  阅读(8)  评论(0编辑  收藏  举报