代码
第一次
var minWindow = function(s, t) {
let l = 0
let r = 0
let isRight = true
let maxStr = ''
let maxNum = 0
const tMapInitial = new Map()
const tMap = new Map()
for(let i = 0; i < t.length; i++) {
tMap.set(t[i], 0)
if(tMapInitial.get(t[i])) {
tMapInitial.set(t[i], tMapInitial.get(t[i]) + 1)
}else {
tMapInitial.set(t[i],1)
}
}
while(r < s.length) {
if(isRight) {
if(tMap.has(s[r])) {
tMap.set(s[r], tMap.get(s[r]) + 1)
}
}else {
if(tMap.has(s[l])) {
tMap.set(s[l], tMap.get(s[l]) - 1)
}
l++
}
let check = 0
for(let [key, value] of tMap.entries()) {
if(value >= tMapInitial.get(key) && value > 0) {
check++
}
}
if(check === tMapInitial.size) {
isRight = false
}else {
isRight = true
}
const locStr = s.substring(l, r+1)
if(check > maxNum) {
maxNum = check
maxStr = locStr
}else if(check == maxNum && check !== 0) {
if(maxStr.length > locStr.length || maxStr === '') {
maxStr = locStr
}
}
if(isRight) {
r++
}
}
if(maxNum !== tMapInitial.size || maxStr.length < t.length) {
return ''
}
return maxStr
};

第二次
var minWindow = function(s, t) {
const need = new Map()
for(let item of t) {
need.set(item, need.has(item) ? need.get(item) + 1 : 1)
}
let l = 0
let r = 0
let res = ''
let needSum = need.size
while(r < s.length) {
const c = s[r]
if(need.has(c)) {
need.set(c, need.get(c) - 1)
if(need.get(c) === 0) {
needSum--
}
}
while(needSum === 0) {
res = (!res || res.length > (r - l + 1)) ? s.substring(l, r + 1) : res
const c2 = s[l]
if(need.has(c2)) {
need.set(c2, need.get(c2) + 1)
if(need.get(c2) === 1) {
needSum++
}
}
l++
}
r++
}
return res
};

相对于法一的优化
- 时间复杂度优化:如何判断滑动窗口是否覆盖t中所有字符?法一重新进行遍历记总和,但是法二是过程中顺便判断记总和。
- 空间复杂度优化:法一使用了两个字典,法二只使用了一个字典。。
思路:滑动窗口
- 建立左右指针
- 先保持左指针不懂,移动右指针。扩大滑动窗口范围,直至包含t中所有字符。
- 移动左指针,右指针保持不动。减小滑动窗口范围,直至不包含t中所有字符。
- 当不包含t中所有字符,重复第2步,直至右指针移动到s串末尾。
时间空间复杂度-法二
- 时间复杂度:O(n + m)
- 空间复杂度:O(m)