76. 最小覆盖子串

100 阅读1分钟

思路

双指针维护一个滑动窗口

移动右指针,包含t的子串时停止

移动左指针,尽量减小滑动窗口长度,当滑动窗口内的字符串不包含t时,左指针停止移动, 右指针移动,直到满足包含t停止,在重复移动左指针。

代码

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
var minWindow = function (s, t) {
    //左右指针
    let l = 0;
    let r = 0;
    //包含t的字典
    const need = new Map()
    for (let i of t){
        //滑动窗口所需的字符和对应字符的个数
        need.set(i,need.has(i) ? need.get(i) + 1 : 1);
    }
    let res = ''
    let needType = need.size;
    //移动右指针
    while (r < s.length) {
        const a = s[r];
        //右指针移动期间对应的字符在字典里的话,字典里对应字符的就-1
        if(need.has(a)){
            need.set(a,need.get(a) - 1);
            if(need.get(a) === 0) needType-- 
        }
        /**
         结束条件:字典里对应的value和为0
         循环一遍太麻烦了,设一个变量needType来当need的长度
         如果1个value为0就--
        */

        //  此时滑动窗口包含t现在该减小长度了,移动左指针
        while(needType === 0){
            const newRes = s.substring(l,r+1)
            if(!res || newRes.length < res.length) res = newRes
            const a = s[l]
            if(need.has(a)){
                //左指针移动期间对应的字符在字典里的话,字典里对应字符的就+1
                 need.set(a,need.get(a) + 1);
                 if(need.get(a) >= 1) needType++ 
            }
            l++;
        }
        r++;
    }
    return res;
};

复杂度

时间:O(t.length + s.length) = O(n)

空间:O(t.length)