76.H 最小覆盖子串
题目
给你一个字符串 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 由英文字母组成
解题思路
滑动窗口法。
通过left和right指针维护一个窗口,找到一个包含所有t中字符的窗口之前,right指针一直右移,当找到包含所有t中字符的窗口之后,尝试将left指针右移,直到窗口不满足要求,或者left超过right为止。然后记录长度最小的窗口。
判断窗口是否包含所有t中字符的方法:维护两个map,ori维护t中的字符个数,cnt维护s中的字符个数,当且仅当cnt中每个字符的数量都不少于ori时,窗口包含t中所有字符。
实现代码
func minWindow(s string, t string) string {
ori, cnt := map[byte]int{}, map[byte]int{}
for i := 0; i < len(t); i++ {
ori[t[i]]++
}
left, right := 0, 0
resLen := len(s) + 1
resLeft, resRight := -1, -1
for left <= right && right < len(s) {
if ori[s[right]] > 0 {
cnt[s[right]]++
for check(ori, cnt) && left <= right {
newLen := right - left + 1
if newLen < resLen {
resLen = newLen
resLeft = left
resRight = right
}
if _, ok := cnt[s[left]]; ok {
cnt[s[left]]--
}
left++
}
}
right++
}
if resLeft == -1 {
return ""
}
return s[resLeft:resRight+1]
}
func check(ori, cnt map[byte]int) bool {
for k, v := range ori {
if cnt[k] < v {
return false
}
}
return true
}
Last updated
Was this helpful?