六、leetcode - 滑动窗口(JS)

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

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
{ a: 1 }             l=0 r=1 res=1 
{ a: 1, b: 1 }       l=0 r=2 res=2 
{ a: 1, b: 1, c: 1 } l=0 r=3 res=3 
{ a: 1, b: 1, c: 1 } l=1 r=4 res=3 
{ a: 1, b: 1, c: 1 } l=2 r=5 res=3 `
{ a: 1, b: 1, c: 1 } l=3 r=6 res=3 
{ a: 0, b: 1, c: 1 } l=5 r=7 res=3 
{ a: 0, b: 1, c: 0 } l=7 r=8 res=3
/**
 * @param {string} s
 * @return {number}
 */
 var lengthOfLongestSubstring = function(s) {
    let l = 0;
    let r = 0;
    let res = 0;
    let map = {}; // 维护一个无重复字符的窗口
    while(r < s.length) {
        let temp = s[r];
        r++; // 窗口内容无重复之前,始终扩张窗口
        map[temp] = (map[temp] || 0) + 1; // 增加窗口内容
        while(map[temp] > 1) { // 窗口内容有重复,则缩小窗口
            map[s[l]]--; // 缩小窗口内容
            l++; // 缩小窗口
        }
        res = Math.max(res, r-l); // 更新最长子串长度
        console.info(map);
        console.info('l='+l);
        console.info('r='+r);
        console.info('res='+res);
    }
    return res;
};
/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
    let l = 0; let r = 0;
    let res = 0; let map = new Map();
    while(r < s.length) {
        while(map.has(s[r])) {
            map.delete(s[l]);
            l++;
        }
        map.set(s[r], 1);
        r++;
        res = Math.max(res, r - l);
    }
    return res;
};
209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
2 l=0 r=1 res=Infinity 
5 l=0 r=2 res=Infinity 
6 l=0 r=3 res=Infinity 
6 l=1 r=4 res=4 
6 l=3 r=5 res=3 
3 l=5 r=6 res=2
/**
 * @param {number} target
 * @param {number[]} nums
 * @return {number}
 */
var minSubArrayLen = function(target, nums) {
    let l = 0; let r = 0;
    let res = Infinity; 
    let sum = 0; // 维护一个子数组的和大于等于target
    while(r < nums.length) {
        let cur = nums[r];
        r++; // 子数组的和大于等于target之前,始终扩张窗口
        sum += cur;
        while(sum >= target) { // 子数组的和大于等于target,则缩小窗口
            res = Math.min(res, r - l); // 更新长度最小的子数组
            sum -= nums[l];
            l++; // 缩小窗口
        }
        console.info(sum);
        console.info('l='+l);
        console.info('r='+r);
        console.info('res='+res);
    }
    return res === Infinity ? 0 : res;
};
904. 水果成篮
输入: [1,2,3,2,2]
输出: 4
解释: 我们可以收集 [2,3,2,2] 如果我们从第一棵树开始,我们将只能收集到 [1, 2]。
{ '1': 1 }                 l=0 r=1 res=1 
{ '1': 1, '2': 1 }         l=0 r=2 res=2 
{ '1': 0, '2': 1, '3': 1 } l=1 r=3 res=2 
{ '1': 0, '2': 2, '3': 1 } l=1 r=4 res=3 
{ '1': 0, '2': 3, '3': 1 } l=1 r=5 res=4
/**
 * @param {number[]} fruits
 * @return {number}
 */
var totalFruit = function(tree) {
    let l = 0; let r = 0;
    let map = {}; // 维护一个连续水果种类为2的窗口
    let count = 0; // 能携带水果的类型,最多2种
    let res = 0; // 能收集的水果树的最大总量
    while(r < tree.length) {
        let cur = tree[r];
        r++; // 收集的连续水果种类大于2之前,始终扩张窗口
        if(map[cur]) {
            map[cur]++;
        } else {
            map[cur] = 1;
            count++; // 增加目前收集的水果类型
        }
        while(count > 2) { // 收集的连续水果种类大于2,缩小窗口
            map[tree[l]]--;
            if(!map[tree[l]]) count--; // 减少目前收集的水果类型
            l++;
        }
        res = Math.max(res, r - l);
        console.info(map);
        console.info('l='+l);
        console.info('r='+r);
        console.info('res='+res);
    }
    return res;
};
1052. 爱生气的书店老板
输入:customers = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], X = 3
输出:16
解释:
书店老板在最后 3 分钟保持冷静。
感到满意的最大客户数量 = 1 + 1 + 1 + 1 + 7 + 5 = 16.
count=0 l=0 r=1 r-l=1 max=0 
count=0 l=0 r=2 r-l=2 max=0 
count=0 l=0 r=3 r-l=3 max=0 
count=2 l=1 r=4 r-l=3 max=2 
count=2 l=2 r=5 r-l=3 max=2 
count=3 l=3 r=6 r-l=3 max=3 
count=1 l=4 r=7 r-l=3 max=3 
count=6 l=5 r=8 r-l=3 max=6
/**
 * @param {number[]} customers
 * @param {number[]} grumpy
 * @param {number} minutes
 * @return {number}
 */
var maxSatisfied = function(customers, grumpy, minutes) {
    let len = grumpy.length;
    let l = 0; let r = 0; 
    let count = 0; // 老板不生气时,顾客满意最大数(每次循环时)
    let max = 0; // 老板不生气时,顾客满意最大数
    while (r < len) {
        if(grumpy[r] === 1) count += customers[r];    
        r++; // 在老板不让自己生气的时间内,始终扩张窗口
        while(r - l > minutes) { // 超出老板不生气的时间后,缩小窗口
            if(grumpy[l] === 1) count -= customers[l];
            l++;
        }
        max = Math.max(max, count); // 更新老板不生气时,顾客满意最大数
        console.info('count='+count);
        console.info('l='+l);
        console.info('r='+r);
        console.info('r-l='+(r-l));
        console.info('max='+max);
    }
    let res = 0; // 不生气时的客户数量
    for (let i = 0; i < len; i++) {
        res += (grumpy[i] === 0 ? customers[i] : 0);
    }
    return res + max;
};
187. 重复的DNA序列

所有 DNA 都由一系列缩写为 ‘A’,‘C’,‘G’ 和 ‘T’ 的核苷酸组成,例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。

编写一个函数来找出所有目标子串,目标子串的长度为 10,且在 DNA 字符串 s 中出现次数超过一次。

输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
输出:["AAAAACCCCC","CCCCCAAAAA"]
{ AAAAACCCCC: 1 } l=1 r=10 
{ AAAAACCCCC: 1, AAAACCCCCA: 1 } l=2 r=11 
{ AAAAACCCCC: 1, AAAACCCCCA: 1, AAACCCCCAA: 1 } l=3 r=12 
{ AAAAACCCCC: 1, AAAACCCCCA: 1, AAACCCCCAA: 1, AACCCCCAAA: 1 } l=4 r=13 
{ AAAAACCCCC: 1, AAAACCCCCA: 1, AAACCCCCAA: 1, AACCCCCAAA: 1, ACCCCCAAAA: 1 } l=5 r=14 
{ AAAAACCCCC: 1, AAAACCCCCA: 1, AAACCCCCAA: 1, AACCCCCAAA: 1, ACCCCCAAAA: 1, CCCCCAAAAA: 1 } l=6 r=15 
{ AAAAACCCCC: 1, AAAACCCCCA: 1, AAACCCCCAA: 1, AACCCCCAAA: 1, ACCCCCAAAA: 1, CCCCCAAAAA: 1, CCCCAAAAAC: 1 } l=7 r=16 
{ AAAAACCCCC: 1, AAAACCCCCA: 1, AAACCCCCAA: 1, AACCCCCAAA: 1, ACCCCCAAAA: 1, CCCCCAAAAA: 1, CCCCAAAAAC: 1, CCCAAAAACC: 1 } l=8 r=17 
{ AAAAACCCCC: 1, AAAACCCCCA: 1, AAACCCCCAA: 1, AACCCCCAAA: 1, ACCCCCAAAA: 1, CCCCCAAAAA: 1, CCCCAAAAAC: 1, CCCAAAAACC: 1, CCAAAAACCC: 1 } l=9 r=18 
{ AAAAACCCCC: 1, AAAACCCCCA: 1, AAACCCCCAA: 1, AACCCCCAAA: 1, ACCCCCAAAA: 1, CCCCCAAAAA: 1, CCCCAAAAAC: 1, CCCAAAAACC: 1, CCAAAAACCC: 1, CAAAAACCCC: 1 } l=10 r=19 
{ AAAAACCCCC: 2, AAAACCCCCA: 1, AAACCCCCAA: 1, AACCCCCAAA: 1, ACCCCCAAAA: 1, CCCCCAAAAA: 1, CCCCAAAAAC: 1, CCCAAAAACC: 1, CCAAAAACCC: 1, CAAAAACCCC: 1 } l=11 r=20 
{ AAAAACCCCC: 2, AAAACCCCCA: 1, AAACCCCCAA: 1, AACCCCCAAA: 1, ... 235 more lines
/**
 * @param {string} s
 * @return {string[]}
 */
var findRepeatedDnaSequences = function(s) {
    let map = {};
    let res = [];
    let l = 0; let r = 9; 
    while(r < s.length) {
        let temp = s.slice(l, r + 1); // 始终维护10个元素的窗口
        map[temp] = (map[temp] || 0) + 1;
        l++;
        r++;
        console.info(map);
        console.info('l='+l);
        console.info('r='+r);
    }
    Object.entries(map).map(([k, v] = [...item]) => {if(v > 1) res.push(k)});
    return res;
};
/**
 * @param {string} s
 * @return {string[]}
 */
var findRepeatedDnaSequences = function(s) {
    let map = new Map();
    let res = [];
    let l = 0; let r = 10;
    while(r <= s.length) {
        let temp = s.slice(l, r);
        map.set(temp, map.has(temp) ? map.get(temp) + 1 : 1);
        l++;
        r++;
    }
    for(let [k, v] of map) {
        if(v > 1) res.push(k);
    }
    return res;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值