力扣热门100题之最小覆盖子串【困难】【滑动窗口】

题目描述

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。

注意:

对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”
解释:最小覆盖子串 “BANC” 包含来自字符串 t 的 ‘A’、‘B’ 和 ‘C’。

示例 2:

输入:s = “a”, t = “a”
输出:“a”
解释:整个字符串 s 是最小覆盖子串。

示例 3:

输入: s = “a”, t = “aa”
输出: “”
解释: t 中两个字符 ‘a’ 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

提示:
在这里插入图片描述
解法1:暴力破解

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
var minWindow = function(s, t) {
    
    
    if(t.length>s.length) return "";
    if(t==s)return s;
    let map=new Map();
    let tempMap=new Map();
    let key="";
    for(let i=0;i<t.length;i++)
    {
    
       
        key=t.charAt(i);
        map.set(key,map.has(key)?map.get(key)+1:1);
    }
    let res="";
    console.log(map)
    for(let i=0;i<s.length;i++){
    
    
        key=s.charAt(i);
        if(map.has(key)){
    
    
            tempMap=new Map(map);
            for(let j=i;j<s.length;j++){
    
    
                key=s.charAt(j);
                if(tempMap.has(key)){
    
    
                    tempMap.set(key,tempMap.get(key)-1);
                    if(tempMap.get(key)==0){
    
    
                        tempMap.delete(key);
                        if(tempMap.size==0){
    
    
                            if(res==""||res.length>j-i){
    
    
                                res=s.substring(i,j+1);
                            }
                            break;
                        }
                    }
                }
                
            }
        }
    }
    return res;
};

执行结果:
在这里插入图片描述

解法2 滑动窗口

var minWindow = function(s, t) {
    
    
			if (t.length > s.length) return "";
			if (t == s) return s;
			let map = new Map();
			let tempMap = new Map();
			let key = "";
			for (let i = 0; i < t.length; i++) {
    
    
				key = t.charAt(i);
				map.set(key, map.has(key) ? map.get(key) + 1 : 1);
				tempMap.set(key, 0);
			}
			let left = -1;
			let minStr = s + ".c";
			for (let i = 0; i < s.length; i++) {
    
    
				key = s.charAt(i);
				if (map.has(key)) {
    
    
					if (left == -1) {
    
    
						left = i;
					}
					tempMap.set(key, tempMap.get(key) + 1)
					while (equals(map, tempMap)) {
    
    
						//找到一个子串
						if (minStr.length > i - left) {
    
    
							minStr = s.substring(left, i + 1);
						}
						//移出最左
						let leftKey = s.charAt(left);
						tempMap.set(leftKey, tempMap.get(leftKey) - 1);
						left++;
						leftKey = s.charAt(left);
						while (!map.has(leftKey)&&left<i) {
    
    
							left++;
							leftKey = s.charAt(left);
						}
						tempMap.set(key, tempMap.get(key) - 1)
						i--;
					}
				}
			}
			return minStr==s+".c"?"":minStr;
		};

		function equals(map, tempMap) {
    
    
			for (let key of map.keys()) {
    
    
				if (map.get(key) > tempMap.get(key)) {
    
    
					return false;
				}
			}
			return true;
		}

执行结果
在这里插入图片描述

滑动窗口优化

var minWindow = function(s, t) {
    
    
			if (t.length > s.length) return "";
			if (t == s) return s;
			let map = new Map();
			let tempMap = new Map();
			let key = "";
			for (let i = 0; i < t.length; i++) {
    
    
				key = t.charAt(i);
				map.set(key, map.has(key) ? map.get(key) + 1 : 1);
				tempMap.set(key, 0);
			}
			let left = -1;
			let minStr = s + ".c";
            let right=0;
            while(left<right&&right<s.length){
    
    
                key=s.charAt(right);
                if (map.has(key)) {
    
    
					if (left == -1) {
    
    
						left = right;
					}
                    tempMap.set(key, tempMap.get(key) + 1)
                    while (equals(map, tempMap)) {
    
    
						//找到一个子串
    
						if (minStr.length > right - left) {
    
    
							minStr = s.substring(left, right + 1);
						}
						//移出最左
						let leftKey = s.charAt(left);
						tempMap.set(leftKey, tempMap.get(leftKey) - 1);
                    	left++;
						leftKey = s.charAt(left);
						while (!map.has(leftKey)&&left<right) {
    
    
							left++;
							leftKey = s.charAt(left);
						}
                        continue;
					}
                }
                right++;
            }
			return minStr==s+".c"?"":minStr;
		};

		function equals(map, tempMap) {
    
    
			for (let key of map.keys()) {
    
    
				if (map.get(key) > tempMap.get(key)) {
    
    
					return false;
				}
			}
			return true;
		}

执行结果:
在这里插入图片描述

解法3 滑动窗口+差值哈希

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
var minWindow = function(s, t) {
    
    
    if (t.length > s.length) return "";
	if (t == s) return s;
    let map = new Map();
    let key = "";
	for (let i = 0; i < t.length; i++) {
    
    
		key = t.charAt(i);
		map.set(key, map.has(key) ? map.get(key) + 1 : 1);
	}
    let count=map.size //记录差值个数
    let left=0;
    let right=0;
    let sLen=s.length;
    let minLen=s.length;
    let minStart=-1;
    while(right<sLen){
    
    
        key=s.charAt(right);
        if(map.has(key)){
    
    
            map.set(key,map.get(key)-1);
            if(map.get(key)==0){
    
    
                count--;//解决一个
                while(count==0){
    
    
                    //得一个 尽量缩短 直到count>0为止 为止后右移指针继续
                    if(minLen>right-left){
    
    
                        minLen=right-left;
                        minStart=left;
                    }
                    //左指针右移
                    key=s.charAt(left);
                    if(map.has(key)){
    
    
                        map.set(key,map.get(key)+1);
                        if(map.get(key)>0){
    
    
                            count++;
                        }
                    }
                    left++;
                }
            }
        }
        right++;    
    }
    return s.substring(minStart,minStart==-1?"":minStart+minLen+1);
};

执行情况:

在这里插入图片描述

滑动窗口+差值哈希 优化

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
var minWindow = function(s, t) {
    
    
    if (t.length > s.length) return "";
	if (t == s) return s;
    let map = new Map();
    let key = "";
	for (let i = 0; i < t.length; i++) {
    
    
		key = t.charAt(i);
		map.set(key, map.has(key) ? map.get(key) + 1 : 1);
	}
    let count=map.size //记录差值个数
    let left=0;
    let right=0;
    let sLen=s.length;
    let minLen=s.length+1;
    let minStart=-1;
    while(right<=sLen){
    
    
        if(count>0){
    
    
            key=s.charAt(right++);
            map.set(key,map.get(key)-1);
            if(map.get(key)==0){
    
    
                count--;
            }
        }else{
    
    
            if(minLen>right-left){
    
    
                minLen=right-left;
                minStart=left;
            }
            key=s.charAt(left++);
            if(map.has(key)){
    
    
                map.set(key,map.get(key)+1);
                if(map.get(key)==1){
    
    
                    count++;
                }
            }
        }
    }
    return minStart==-1?"":s.substring(minStart,minLen+minStart);
};

执行结果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_33183456/article/details/131926931
今日推荐