莲都区建设局门户网站,外贸网站dns,微信公众号登录二维码,百度搜索电话文章目录 1.问题描述2.难度等级3.热门指数4.解题思路参考文献 1.问题描述
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串#xff0c;则返回空字符串 “” 。
注意#xff1a;
对于 t 中重复字符#xff… 文章目录 1.问题描述2.难度等级3.热门指数4.解题思路参考文献 1.问题描述
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串则返回空字符串 “” 。
注意
对于 t 中重复字符我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。如果 s 中存在这样的子串我们保证它是唯一的答案。
示例 1
输入s ADOBECODEBANC, t ABC
输出BANC
解释最小覆盖子串 BANC 包含来自字符串 t 的 A、B 和 C。示例 2
输入s a, t a
输出a
解释整个字符串 s 是最小覆盖子串。示例 3
输入: s a, t aa
输出:
解释: t 中两个字符 a 均应包含在 s 的子串中
因此没有符合条件的子字符串返回空字符串。提示
m s.length
n t.length
1 m, n 105
s 和 t 由英文字母组成2.难度等级
Hard。
3.热门指数
★★★★☆
4.解题思路
问题要求返回字符串 s 中包含字符串 t 的全部字符的最小字串。我们可以将最小子串看成一个窗口我们称包含 t 全部字母的窗口为「可行窗口」。
所以我们可以尝试用滑动窗口的思想解决这个问题。
在滑动窗口类型的问题中都会有两个指针一个用于「延伸」现有窗口的 r 指针和一个用于「收缩」窗口的 l 指针。在任意时刻只有一个指针运动而另一个保持静止。我们在 s 上滑动窗口通过移动 r 指针不断扩张窗口。当窗口包含 t 全部所需的字符后如果能收缩我们就收缩窗口直到得到最小窗口。 如何判断当前的窗口包含所有 t 所需的字符呢我们可以用一个哈希表表示 t 中所有的字符以及它们的个数用一个哈希表动态维护窗口中所有的字符以及它们的个数如果这个动态表中包含 t 的哈希表中的所有字符并且对应的个数都不小于 t 的哈希表中各个字符的个数那么当前的窗口是「可行」的。
注意 这里 t 中可能出现重复的字符所以我们要记录字符的个数。
时间复杂度 最坏情况下左右指针对 s 的每个元素各遍历一遍哈希表中对 s 中的每个元素各插入、删除一次。对 t 中的元素各插入一次。左右指针每次移动都要检查窗口是否「可行」每次检查是否可行会遍历整个 t 的哈希表。哈希表的大小与字符集的大小有关设字符集大小为 C则时间复杂度为O(Cmn)其中 m 为 s 长度n 为 t 长度。
空间复杂度 这里用了两张哈希表作为辅助空间每张哈希表最多不会存放超过字符集大小的键值对我们设字符集大小为 C 则渐进空间复杂度为O(C)。
下面以 Golang 为例给出实现。
func minWindow(s string, t string) string {mt : make(map[rune]int)for _, c : range t {mt[c]}var minl, minr int // 最小窗口左右下标var winlen int // 最小窗口长度var l, r int // 滑动窗口左右下标m : make(map[rune]int) // 窗口内字符数for ; r len(s); r {m[rune(s[r])]if !cover(m, mt) {continue}for ; l r; l {m[rune(s[l])]--if !cover(m, mt) {if winlen 0 || r-l1 winlen {minl, minr l, rwinlen r - l 1}// 当前元素被删除所以滑动窗口起始下标要移到下一位lbreak}}}if winlen 0 {return s[minl : minr1]}return
}func cover(m, mt map[rune]int) bool {for k, v : range mt {if m[k] v {return false}}return true
}参考文献
76. 最小覆盖子串 - LeetCode