slideWindow(s, t){// 定义需要个数的对象、当前窗口对象const need ={}const window ={}// 定义左右索引let left =0let right =0// valid种类数let valid =0// 找最小子串let start =0let len =Infinity// 结果数组: 多个异位词、最长子串长度let res =[]<!--需要对象赋值-->for(const i of t){
need[i]=(need[i]||0)+1}<!--遍历子串s-->while(right < s.length){<!--右索引移动-->const r = s[right]
right++<!--更新窗口:-->// 当前字符串为需要,窗口对象属性值+1,加1后若当前属性个数与需要个数相等,种类数valid++// 无重复子串窗口更新只需: 窗口数window[r]+1if(need[r]){
window[r]=(window[r]||0)+1if(window[r]=== need[r]) valid++}<!--收缩窗口-->// 1、最小覆盖子串:当前种类数等于需要的种类数(结果长度!==需要长度)// 2、字符串排列、异位词:当前范围大于等于需要的长度(结果长度===需要长度)// 3、无重复子串:窗口属性个数window[r] > 1while(valid === Object.keys(need).length){// while (right - left >= t.length)// while (window[r] > 1)const l = s[left]<!--判断当前满足条件则处理结果-->// 1、最小覆盖子串:如果当前范围小于上次算的子串长度,则更新最小覆盖子串开始索引和长度if(right - left < len){
start = left
len = right - left
}// 2、字符串排列、异位词:如果种类数===需要对象属性长度,则产生结果if(valid === Object.keys(need).length){returntrue// 异位词: res.push(left)}// 3、无重复子串无需处理:再外部循环判断<!--左索引移动-->
left++<!--更新窗口-->// 当前字符串需要,如果窗口数===需要数,种类--,下次则退出循环// 窗口数--// 1、2、3:最小覆盖子串、字符串排列、异位词if(need[l]){if(window[l]=== need[l]) valid--
window[l]--}// 4:无重复子串只需
window[l]--}// 无重复子串在收缩窗口后更新结果
res = Math.max(res, right - left)}<!--while循环后返回结果-->return len ===Infinity?'': s.substr(start, len)returnfalsereturn res
}
实例
76.最小覆盖子串
const s ='agblalbu'const t ='ab'
console.error(this.minCoverSubstring(s, t))
输出:agb
minCoverSubstring(s, t){// 定义需要字符串个数的对象、当前窗口需要字符串个数的对象const need ={}const window ={}// 定义左右索引、当前种类数let left =0let right =0let valid =0// 定义最小字符串的起始索引和长度let start =0let len =Infinity<!--需要对象赋值-->for(const i of t){
need[i]=(need[i]||0)+1}// 遍历子串while(right < s.length){// 右索引右移const r = s[right]
right++// 如果当前字符串在需要列表中则当前窗口对应的字符串的个数加1if(need[r]){// window[r]++
window[r]=(window[r]||0)+1// 如果当前字符串需要的个数已全,则种类数加1if(window[r]=== need[r]) valid++}// 判断收缩窗口(当前种类数等于需要的种类数)while(valid === Object.keys(need).length){// 更新最小覆盖子串if(right - left < len){
start = left
len = right - left
}// 左索引右移const l = s[left]
left++// 如果当前字符串在需要的窗口,当前窗口的种类数-1,且如果当前字符的种类数和需要种类数,种类数-1,// 一旦减1则不再满足条件,退出循环if(need[l]){if(window[l]=== need[l]) valid--
window[l]--}}}return len ===Infinity?'': s.substr(start, len)}
567.字符串的排列
const s1 ='agbalapbu'const t1 ='ab'
console.error(this.stringRank(s, t))
输出:truestringRank(s, t){// 定义需要字符串个数的对象、当前窗口需要字符串个数的对象、结果const need ={}const window ={}// 定义左右索引、种类值let left =0let right =0let valid =0// 需要对象赋值for(const i of t){
need[i]=(need[i]||0)+1}// 遍历s字符串while(right < s.length){const r = s[right]
right++// 右移右索引,如果当前字符串为需要的则更新当前窗口,更新后如果个数与需要相同,则种类数+1if(need[r]){
window[r]=(window[r]||0)+1if(window[r]=== need[r]) valid++}// 当当前范围大于等于t长度,则收缩窗口或判断结果while(right - left >= t.length){// 如果种类数等于需要对象长度,则true,// 否则如果当窗口数为种类数,则种类数减1、当前窗口数减1,继续缩小窗口const l = s[left]if(valid === Object.keys(need).length){returntrue}
left++if(need[l]){if(window[l]=== need[l]) valid--
window[l]--}}}returnfalse}
438.找到字符串中所有字母的异位词
const s2 ='cabhbacj'const t2 ='abc'
console.error(this.HeterotopicWords(s2, t2))
输出:[0,4]HeterotopicWords(s, t){// 定义需要、当前const need ={}const window ={}const res =[]// 定义左右索引,种类数let left =0let right =0let valid =0// 赋值for(const i of t){
need[i]=(need[i]||0)+1}// 遍历swhile(right < s.length){// right++const r = s[right]
right++// 如果当前值为需要,窗口window++,如果窗口window和需要need的个数相同,则种类++if(need[r]){
window[r]=(window[r]||0)+1if(window[r]=== need[r]) valid++}// 收缩窗口(注意>=)while(right - left >= t.length){const l = s[left]// 种类数valid为需要数则索引入数组if(valid === Object.keys(need).length){
res.push(left)// res.push(s.substr(left, t.length))}
left++// 如果当前为需要,且如果窗口数=需要数,种类数--,窗口数--if(need[l]){if(window[l]=== need[l]) valid--
window[l]--}}}return res
},
3.无重复字符的最长子串
const s3 ='pwwkew'
console.error(this.maxNoRepeatSubString(s3))输出:3(wke)maxNoRepeatSubString(s){// 定义需要、当前窗口、左右索引、结果const window ={}let left =0let right =0let res =0// 遍历swhile(right < s.length){const r = s[right]
right++// 窗口更新
window[r]=(window[r]||0)+1// 收缩while(window[r]>1){const l = s[left]
left++
window[l]--}
res = Math.max(res, right - left)}return res
}```/