题目
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
示例 2:
输入:s = "a", t = "a"
输出:"a"
示例 3:
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
思路
继上一篇 LC904 - 水果成篮, 这道题的解法也是滑动窗口。
我们需要统计 t 中字符的种类和个数,这是为了方便判断 t 是否被包含在 s 的子串中。
代码
func minWindow(s string, t string) string {
result := ""
resultLen := math.MaxInt32
sHashmap := map[uint8]int{
}
tHashmap := map[uint8]int{
}
// 统计 t 字符串中的 字符及个数
for i := 0; i < len(t); i ++ {
tHashmap[t[i]] ++
}
left, right, length := 0, 0, len(s)
for ; right < length; right ++ {
// 每向右滑动一格
sHashmap[s[right]] ++
// 判断当前窗口是否满足条件
for ;left <= right && check(sHashmap, tHashmap); {
// 满足条件了,更新一下结果
if resultLen > right - left + 1 {
resultLen = right - left + 1
result = s[left : right + 1]
}
// 结果更新后,便可以缩小滑动窗口大小,即 left++
sHashmap[s[left]] --
// 如果字符为0了删除
if sHashmap[s[left]] == 0 {
delete(sHashmap, s[left])
}
left ++
}
}
return result
}
func check(sHashmap, tHashmap map[uint8]int) bool {
for item := range tHashmap {
sNum, ok := sHashmap[item]
if !ok || sNum < tHashmap[item] {
return false
}
}
return true
}