JavaScript滑动窗口算法

247 阅读1分钟

滑动窗口的思路

增加窗口右边界,寻找一个可行解,在找到可行解的情况下增加窗口左边界,优化可行解,找到最优解

/* 滑动窗口算法框架 */
const slidingWindow = (s, t) => {
    let need = new Map(), window = new Map();
    for (let c of t){ 
        need.set(c, (need.get(c) || 0) + 1);
    } 
    let left = 0, right = 0, valid = 0;
    // 记录最小覆盖子串的起始索引及⻓度 
    let start = 0, len = Number.MAX_SAFE_INTEGER;
    while (right < s.length) {
        // c 是将移入窗口的字符
        const c = s[right];
        // 右移窗口
        right++;
        // 进行窗口内数据的一系列更新
        /*
        if(need.has(c)) {
          window.set(c, (window.get(c) || 0) + 1);
          if (window.get(c) == need.get(c)) {
              valid++;
          }
        }
        */

        /*** debug 输出的位置 ***/
        console.log("window", left, right);

        // 判断左侧窗口是否要收缩
        while (valid == need.size) {
            // 在这里更新最小覆盖子串
            /*
            if (right - left < len) {
                start = left;
                len = right - left; 
            }
            */
            // d 是将移出窗口的字符
            const d = s[left];
            // 左移窗口
            left++;
            // 进行窗口内数据的一系列更新
            /*
            if(need.has(d)) {
              if (window.get(d) == need.get(d)) {
                  count--;
              }
              window.set(d, window.get(d) - 1);
            }
            */
        }
    }
    return len == Number.MAX_SAFE_INTEGER ? '' : s.substr(start, len);
}

一、最长无重复子串

function getMaxLenNorepeatStr(str){
    let size = 1, //无重复字符串的长度
      currentStr = '', //用来存储临时分割的最新一段字符串
      norepeatStr = ''; // 结果字符串
    
    for(let i = 0; i < str.length; i++) {
      if(currentStr.includes(str[i])) {
        currentStr = currentStr.slice(i + 1) + str[i];
      } else {
        currentStr = currentStr + str[i];
      }
      
      if(size < currentStr.length) {
        size = currentStr.length;
        norepeatStr = currentStr;
      }
    }
    return norepeatStr;
  }
  getMaxLenNorepeatStr('abcadb')  // 'bcad'