js滑动窗口算法

5 篇文章 0 订阅
2 篇文章 0 订阅

框架

slideWindow (s, t) {
 	// 定义需要个数的对象、当前窗口对象
    const need = {}
    const window = {}
 	// 定义左右索引
    let left = 0
    let right = 0
 	// valid种类数
    let valid = 0
 	// 找最小子串
    let start = 0
    let len = Infinity
 	// 结果数组: 多个异位词、最长子串长度
    let res = []
    
    <!--需要对象赋值-->
    for (const i of t) {
        need[i] = (need[i] || 0) + 1
    }
    
    <!--遍历子串s-->
    while (right < s.length) {
        <!--右索引移动-->
        const r = s[right]
        right++
        
        <!--更新窗口:-->
        // 当前字符串为需要,窗口对象属性值+1,加1后若当前属性个数与需要个数相等,种类数valid++
        // 无重复子串窗口更新只需: 窗口数window[r]+1
        if (need[r]) {
          window[r] = (window[r] || 0) + 1
          if (window[r] === need[r]) valid++
        }
        
        <!--收缩窗口-->
        // 1、最小覆盖子串:当前种类数等于需要的种类数(结果长度!==需要长度)
        // 2、字符串排列、异位词:当前范围大于等于需要的长度(结果长度===需要长度)
        // 3、无重复子串:窗口属性个数window[r] > 1
        while (valid === Object.keys(need).length) {
        // while (right - left >= t.length)
        // while (window[r] > 1)
            const l = s[left]
            <!--判断当前满足条件则处理结果-->
            // 1、最小覆盖子串:如果当前范围小于上次算的子串长度,则更新最小覆盖子串开始索引和长度
            if (right - left < len) {
                start = left
                len = right - left
            }
            // 2、字符串排列、异位词:如果种类数===需要对象属性长度,则产生结果
            if (valid === Object.keys(need).length) {
                return true
                // 异位词: res.push(left)
            }
            // 3、无重复子串无需处理:再外部循环判断
            <!--左索引移动-->
            left++
            
            <!--更新窗口-->
            // 当前字符串需要,如果窗口数===需要数,种类--,下次则退出循环
            // 窗口数--
            // 1、2、3:最小覆盖子串、字符串排列、异位词
            if (need[l]) {
                if (window[l] === need[l]) valid--
                window[l]--
             }
             // 4:无重复子串只需
             window[l]--
        }
        // 无重复子串在收缩窗口后更新结果
         res = Math.max(res, right - left)
    }
    <!--while循环后返回结果-->
    return len === Infinity ? '' : s.substr(start, len)
    return false
    return res
}

实例

76.最小覆盖子串

const s = 'agblalbu'
const t = 'ab'
console.error(this.minCoverSubstring(s, t))
输出:agb

minCoverSubstring (s, t) {
  // 定义需要字符串个数的对象、当前窗口需要字符串个数的对象
  const need = {}
  const window = {}
  // 定义左右索引、当前种类数
  let left = 0
  let right = 0
  let valid = 0
  // 定义最小字符串的起始索引和长度
  let start = 0
  let len = Infinity
  <!--需要对象赋值-->
  for (const i of t) {
    need[i] = (need[i] || 0) + 1
  }
  
  // 遍历子串
  while (right < s.length) {
    // 右索引右移
    const r = s[right]
    right++
    // 如果当前字符串在需要列表中则当前窗口对应的字符串的个数加1
    if (need[r]) {
      // window[r]++
      window[r] = (window[r] || 0) + 1
      // 如果当前字符串需要的个数已全,则种类数加1
      if (window[r] === need[r]) valid++
    }
    // 判断收缩窗口(当前种类数等于需要的种类数)
    while (valid === Object.keys(need).length) {
      // 更新最小覆盖子串
      if (right - left < len) {
        start = left
        len = right - left
      }
      // 左索引右移
      const l = s[left]
      left++
      // 如果当前字符串在需要的窗口,当前窗口的种类数-1,且如果当前字符的种类数和需要种类数,种类数-1,
      // 一旦减1则不再满足条件,退出循环
      if (need[l]) {
        if (window[l] === need[l]) valid--
        window[l]--
      }
    }
  }
  return len === Infinity ? '' : s.substr(start, len)
}

567.字符串的排列

const s1 = 'agbalapbu'
const t1 = 'ab'
console.error(this.stringRank(s, t))
输出:true

stringRank (s, t) {
  // 定义需要字符串个数的对象、当前窗口需要字符串个数的对象、结果
  const need = {}
  const window = {}
  // 定义左右索引、种类值
  let left = 0
  let right = 0
  let valid = 0
  // 需要对象赋值
  for (const i of t) {
    need[i] = (need[i] || 0) + 1
  }

  // 遍历s字符串
  while (right < s.length) {
    const r = s[right]
    right++
    // 右移右索引,如果当前字符串为需要的则更新当前窗口,更新后如果个数与需要相同,则种类数+1
    if (need[r]) {
      window[r] = (window[r] || 0) + 1
      if (window[r] === need[r]) valid++
    }
    // 当当前范围大于等于t长度,则收缩窗口或判断结果
    while (right - left >= t.length) {
      // 如果种类数等于需要对象长度,则true,
      // 否则如果当窗口数为种类数,则种类数减1、当前窗口数减1,继续缩小窗口
      const l = s[left]
      if (valid === Object.keys(need).length) {
        return true
      }
      left++
      if (need[l]) {
        if (window[l] === need[l]) valid--
        window[l]--
      }
    }
  }
  return false
}

438.找到字符串中所有字母的异位词

const s2 = 'cabhbacj'
const t2 = 'abc'
console.error(this.HeterotopicWords(s2, t2))
输出:[0, 4]

HeterotopicWords (s, t) {
  // 定义需要、当前
  const need = {}
  const window = {}
  const res = []
  // 定义左右索引,种类数
  let left = 0
  let right = 0
  let valid = 0
  // 赋值
  for (const i of t) {
    need[i] = (need[i] || 0) + 1
  }
  // 遍历s
  while (right < s.length) {
    // right++
    const r = s[right]
    right++
    // 如果当前值为需要,窗口window++,如果窗口window和需要need的个数相同,则种类++
    if (need[r]) {
      window[r] = (window[r] || 0) + 1
      if (window[r] === need[r]) valid++
    }
    // 收缩窗口(注意>=)
    while (right - left >= t.length) {
      const l = s[left]
      // 种类数valid为需要数则索引入数组
      if (valid === Object.keys(need).length) {
        res.push(left)
        // res.push(s.substr(left, t.length))
      }
      left++
      // 如果当前为需要,且如果窗口数=需要数,种类数--,窗口数--
      if (need[l]) {
        if (window[l] === need[l]) valid--
        window[l]--
      }
    }
  }
  return res
},

3.无重复字符的最长子串

const s3 = 'pwwkew'
console.error(this.maxNoRepeatSubString(s3))
输出:3 (wke)

maxNoRepeatSubString(s) {
  // 定义需要、当前窗口、左右索引、结果
  const window = {}
  let left = 0
  let right = 0
  let res = 0
  // 遍历s
  while (right < s.length) {
    const r = s[right]
    right++
    // 窗口更新
    window[r] = (window[r] || 0) + 1

    // 收缩
    while (window[r] > 1) {
      const l = s[left]
      left++
      window[l]--
    }
    res = Math.max(res, right - left)
  }
  return res
}
```/
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 为了实现多输入多输出时的动态窗口大小,您可以考虑使用JavaScript和HTML5中的动态事件来实现。下面是一些实现的建议: 1. 监听窗口大小改变的事件。您可以使用JavaScript中的window.onresize事件,以便在窗口大小发生变化时重新调整输入和输出窗口的大小。 2. 动态调整输入和输出窗口的大小。您可以使用JavaScript中的DOM操作,例如document.getElementById()方法,来获取输入和输出窗口的元素,并根据窗口大小的变化来动态调整它们的大小。 3. 监听鼠标滚动事件。您可以使用JavaScript中的addEventListener()方法来添加鼠标滚动事件监听器,以便在输入窗口内容过长时,用户可以通过滚动鼠标滚轮来浏览全部内容。 4. 监听键盘事件。您可以使用JavaScript中的addEventListener()方法来添加键盘事件监听器,以便在用户输入过多内容时,自动扩大输入窗口的大小,以适应输入内容。 总之,使用JavaScript和HTML5中的动态事件可以实现动态窗口大小的输入和输出。 ### 回答2: 在多输入多输出时间预测问题中,滑动窗口输入可以通过以下方式实现: 1. 定义窗口大小:首先要决定滑动窗口的大小,这个大小是根据具体的问题和数据特征来决定的,可以根据经验设置或者通过交叉验证确定。 2. 确定滑动步长:滑动窗口的步长决定了每次滑动窗口的间隔,同样需要根据问题和数据特征来决定。步长过小会导致冗余的计算,步长过大会导致信息的丢失。 3. 数据重叠:为了提高模型的可靠性和泛化能力,通常在滑动窗口实现中会采用数据重叠的方式。即每次滑动窗口移动时,新窗口的数据包括前一个窗口的一部分数据,这样可以使模型在不同时间段的数据中进行学习和预测。 4. 形成训练样本:通过滑动窗口的方式,可以将原始数据序列划分成多个子序列。每个子序列可以看作是一个训练样本,其中包含了窗口内的数据作为输入特征,以及窗口外的数据作为输出特征。通过这样的方式,可以获得一系列训练样本用于建立模型。 5. 迭代训练:在实际应用中,通常需要根据滑动窗口的大小和步长,多次进行滑动窗口的迭代训练。每次迭代训练时,可以调整模型参数、优化算法等,以进一步提高模型的性能和预测效果。 滑动窗口输入的实现能够充分利用时间序列数据的时序性特点,提供了一种便捷且有效的方式来建立时间预测模型。同时,根据具体的问题和数据特征,我们可以进行灵活的调整和优化来适应不同的场景和需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值