leetcode——最小覆盖字串(滑动窗口)

题目
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。

示例:
输入: S = “ADOBECODEBANC”, T = “ABC”
输出: “BANC”

说明:
如果 S 中不存这样的子串,则返回空字符串 “”。
如果 S 中存在这样的子串,我们保证它是唯一的答案。

解析

  • 新建对象obj记录t中每种字符串出现的次数,并记录t中的字符串种类数target
var obj = {
    
    }
for(let c of t){
    
    
   if(c in obj) obj[c]++
   else obj[c] = 1
}
target = Object.keys(obj) //3

obj的结果为

obj = {
    
    
   'A' : 1,
   'B' : 1,
   'C': 1
}
  • left、right为满足要求的滑动窗口的左右边界
var left = -1,right = -1
  • i、j是当前滑动窗口的左右边界,count为滑动窗口中已经满足t中的字符数。遍历s中的每一项,当s[i]的值是t中的字符,obj[s[i]]–。当obj[s[i]] == 0时表示i~j中s[i]需要出现的次数已经足够,count++。当count = target时,表示当前窗口已经满足s中出现t的条件
for(let i = 0, j = 0; j <  s.length; j++){
    
    
	//当前窗口新进来的值在obj中
	if(s[j] in obj){
    
    
		 obj[s[i]]--
		  //s[i]出现的次数足够时,count++
		  if(obj[s[i]] == 0) count++
		  //当前窗口最左边的字符无用或者出现次数>需要次数,可丢弃
		  while(((s[i] in obj) && obj[s[i]] < 0) || (! s[i] in obj)){
    
    
			  if(s[i] in obj) obj[s[i++]]++
			  else i++
		  }
		  //当前窗口已经出现t中所有字符
		  if(count == target){
    
    
		  	//记录最短的满足要求的滑动窗口
		  	if(left == -1 && right == -1 || right - left + 1 > j - i + 1){
    
    
		  		left = i
		  		right = j
		  	}
	}
}

代码

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
var minWindow = function(s, t) {
    
    
    //记录t中每个字符需要出现的次数
    let obj = {
    
    };
    for(let c of t){
    
    
        if(c in obj){
    
    
            obj[c]++;
        }else{
    
    
            obj[c] = 1;
        }
    }
  
    
    //滑动窗口的左右边界
    var left = -1,right = -1;
    //count为滑动窗口中出现t中字符的种类数
    var count = 0,target = Object.keys(obj).length;

    for(let i = 0, j = 0 ; j < s.length; j++){
    
    
//         console.log('s[j]='+s[j]);
        //新进来的值是t中的值j
        if(s[j] in obj){
    
    
            obj[s[j]]--;
//             console.log('obj[s[j]]='+obj[s[j]]);
            //滑动窗口中s[i]出现的次数已经足够
            if(obj[s[j]] == 0) count++;
            while((s[i] in obj) && obj[s[i]] < 0 || !(s[i] in obj)) {
    
    
//               console.log('s[i]='+s[i]);
//               console.log('obj[s[i]]='+obj[s[i]]);
              //滑动窗口左移一位
              if(s[i] in obj) obj[s[i++]]++;
              else i++;
            }  
            //滑动窗口包含t中所有字符
            if(count == target){
    
    
                if(left == -1 && right == -1 || right - left + 1 > j - i + 1 ){
    
    
//                     console.log(i,j);
                    left = i;
                    right = j;
                }
            }
        } 
        
    }
    if(left == -1) return "";
    return s.slice(left,right+1);
};

猜你喜欢

转载自blog.csdn.net/weixin_42937036/article/details/106306938