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);
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值