leetcode -- 滑动窗口专题

75 阅读1分钟

76.最小覆盖子串

76最小覆盖子串.jpg

具体的解题思路和代码我放到了下面供大家参考:

var minWindow = function(s, t) {
    let left = 0, right = 0, vaild = 0;
    let need = {};
    let win_map = {};
    // 装填需要的子串
    for (let key of t) {
        need[key] = (need[key] || 0) + 1;
    }
    console.log(need);

    // 记录最小覆盖子串的起始索引及其长度  多的
    let start = 0, len = Number.MAX_VALUE;
    // 开始窗口右移
    while(right < s.length) {
        // c 是将移入窗口的字符
        let c = s[right];
        // 右移窗口
        right++;
        // 进行窗口内数据的一系列更新
        if (need[c]) {
            win_map[c] = (win_map[c] || 0) + 1;
            if (win_map[c] === need[c]) {
                vaild++;
            }
        }

        // 判断左侧窗口是否要收缩,以及收缩条件是什么
        while(vaild === Object.keys(need).length) {
            // 这里更新最小覆盖子串
            console.log('right', right, 'left', left);
            if (right - left < len) {
                start = left;
                len = right - left;
                console.log('len', len);
            }
            // d 是将移出窗口的字符
            let d = s[left];
            // 左移窗口
            left++;
            // 进行窗口内数据的一系列更新
            if(need[d]) {
                if (win_map[d] === need[d]) {
                    vaild--;   
                }
                win_map[d]--;
            }
        }
    }
    // 返回最小的覆盖子串
    return len === Number.MAX_VALUE ? "" : s.substr(start, len);
};

这里还需要注意 for offor in 使用上的不同

let s = 'abc'
let s_obj = {};
for(let i of s) {
   s_obj[i] = (s_obj[i] || 0) + 1
}
// {a: 1, b: 1, c: 1}

let l_obj = {};
for(let i in s) {
   l_obj[i] = (s_obj[i] || 0) + 1
}

//  {0: 1, 1: 1, 2: 1}

567. 字符串的排列

567.jpg

解题思路:

var checkInclusion = function(s1, s2) {
    let left = 0, right = 0, valid = 0;
    let need = {}, win_obj = {};
    // 装填需要的子串
    for (let k of s1) {
        need[k] = (need[k] || 0) + 1;
    }
    console.log('need', need);

    // let start = 0, len = Number.MAX_VALUE; 不要了
    // right 开始滑动窗口 ---> 怎么滑不会遍历啊
    while(right < s2.length) { // 最后困在这里了
        let c = s2[right];
        right++;

        if (need[c]) { // 合法写入
            win_obj[c] = (win_obj[c] || 0) + 1;
            if (win_obj[c] === need[c]) {
                valid++;
            }
        }

        // left 出场了左边 需要减小滑动窗口
        while(right - left >= s1.length) { // 最后困在这里了
            if (valid === Object.keys(need).length) {
                return true;
            }
            // 如果暂时没有找到合法的怎么办呢? 左移减小区间
            let d = s2[left];
            left++;  // left 没更新
            if (need[d]) {  // 这边要对称的合法的输出
                // valid--; 少了
                if (win_obj[d] === need[d]) {
                    valid--;
                }
                win_obj[d]--;
            }
        }
    }
    return false;
};

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

438.jpg

解题思路:

var findAnagrams = function(s, p) {
    let need = {}, window ={};
    let left = 0, right = 0;
    // 装填需要的子串
    for (let k of p) {
        need[k] = (need[k] || 0) + 1;
    }
    console.log(need);

    let valid = 0, res = [];
    // 右移
    while(right < s.length) {
        let c = s[right];
        right++;
        // window[c] = (window[c] || 0) + 1;
        if (need[c]) {  // 
            window[c] = (window[c] || 0) + 1;
            if (window[c] === need[c]) {
                valid++;
            }
        }

        while(right - left >= p.length) { //right - left > p.length  [0,5,6]
            // 满足条件的情况下
            if (valid === Object.keys(need).length) {
                console.log('left', left);
                res.push(left);
            }
            // 否则
            let d = s[left];
            left++;
            // 窗口更新 ---> 不会
            if (need[d]) {
                if (window[d] === need[d]) {
                    valid--
                }
                window[d]--;
            }
        }
    }
    return res;
};

3. 无重复最长子串

03.jpg

解题思路:

var lengthOfLongestSubstring = function(s) {
    let left = 0, right = 0, window = new Set();
    let res = 0; //记录结果
    while(left < s.length) {
        while(right < s.length && !window.has(s[right])) {
            window.add(s[right])
            right++;
        }
        // 不满足上述条件--左侧窗口要收缩
        res = Math.max(res, right - left);
        window.delete(s[left]);
        left++;
    }
   return  res;
};

76.最小覆盖子串

567. 字符串的排列

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

3. 无重复最长子串

参考学习资料

学习链接