题目描述:
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
题目分析:
看到这类最长最短子串等,则首选滑动窗口方法。按照滑动窗口的方法,重点应该是确定满足要求时窗口的状态: 这里是包含字符串t的所有元素就可以,不要求有序,那么使用哈希表来记录就是很好的办法,同时要求最短,即后续要优化,因为可能T的元素会在s中常重复出现,那么哈希表的值设置为频率就能很好达到——》元素出现,并且频率一次就是最短的状态。因为是字符,所以哈希表设计为 var targetFreq :=map[byte]int
。 那么targetFreq的长度就代表了目标字符串的元素种类。
点击查看代码
func minWindow(s string, t string) string { if len(s)==0 || len(t)==0{return ""} left,right,matchCount:=0,0,0 //记录最短序列的开始位置,结合最短长度即可得到最短序列 start:=0 //记录最短长度 minLength := len(s)+1 //记录目标序列的元素的种类和个数。这样无论元素是否有重复,只要这两个要求都满足就可以 targetFreq := make(map[byte]int) for i := 0; i < len(t); i++ { targetFreq[t[i]]++ } //用于记录当前窗口中的元素种类数量情况 windowFreq := make(map[byte]int) for right<len(s){ charRight := s[right] right++ //只统计目标序列中的元素即可。 if _,exists:=targetFreq[charRight];exists{ windowFreq[charRight]++ //如果某个元素的数量已经满足了目标序列的数量要求,那么完成的元素数量++ if windowFreq[charRight] == targetFreq[charRight] { matchCount++ } } //所有元素数量已经符合要求,现在看能否缩小序列 for matchCount == len(targetFreq){ if right-left <minLength{ minLength = right-left start = left } charLeft:= s[left] left++ // 尝试缩小边界 if _,exists:=targetFreq[charLeft];exists{ if windowFreq[charLeft] == targetFreq[charLeft]{ matchCount-- } windowFreq[charLeft]-- } } } if minLength == len(s)+1{return ""} return s[start:start+minLength] }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~