给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
示例 2:
输入:s = "a", t = "a"
输出:"a"
提示:
- 1 <= s.length, t.length <= 105
- s 和 t 由英文字母组成
1 /** 2 * @param {string} s 3 * @param {string} t 4 * @return {string} 5 */ 6 var minWindow = function(s, t) { 7 let l = 0; 8 let r = 0; 9 const need = new Map(); //判断需要的字符以及它们的个数 10 for( let c of t) { //遍历一下t字符串 11 need.set(c, need.has(c) ? need.get(c) + 1 : 1); //如果之前设置过则+1,没有设置过则初始化为1 12 } //遍历之后,就可以知道滑动窗口需要的字母及它们需要出现的次数 13 let needType = need.size; //就是t中需要匹配的字母的个数 14 let res =''; //让res来记录最小子串 15 while(r<s.length) { 16 const c = s[r]; //右指针向右滑动的工程中可以模拟 17 if(need.has(c)){ //如果右指针所指的字符在需求列表里面,也就是在t里面,所以只要包含了一个就减一 18 need.set(c , need.get(c) - 1); 19 if(need.get(c) === 0) needType -= 1;//need里某一个字母的值变为0了,说明全部都匹配到了,所以总的需要匹配的字母个数减一 20 } 21 while(needType === 0) { //当移动右指针直到包含了所有需要的字母之后,开始移动左指针,找最小的字符串 22 const newRes = s.substring(l, r+1); 23 if(!res || newRes.length < res.length) res = newRes; //如果一开始是空字符串,就先赋值为newRes 24 const c2 = s[l]; //左指针当前的字符 25 if(need.has(c2)){ 26 need.set(c2, need.get(c2) + 1); //因为左指针一移动,本来需要在t里面的字符,现在不在或者数量不匹配了,所以要+1 27 if(need.get(c2) === 1) needType +=1; //说明左指针不能移动了,因为现在字符串内没有完全包含t,已经不满足要求了 28 } 29 l+=1; 30 } 31 r+=1; //需要重新移动右指针,直到匹配了t中的所有字符 32 } 33 return res; 34 };