题目描述:
给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同 。
s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。
例如,如果 words = ["ab","cd","ef"], 那么 "abcdef", "abefcd","cdabef", "cdefab","efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。
返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。
示例 1:
输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]
解释:因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 "barfoo" 开始位置是 0。它是 words 中以 ["bar","foo"] 顺序排列的连接。
子串 "foobar" 开始位置是 9。它是 words 中以 ["foo","bar"] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。
题目分析:
题目希望找到s中字符数组的字符串的所有排列组合的开始下标。注意题目提到的对所有条件的标示,字符数组的字符串的长度的长度是相同的。设置这个条件自然是有用的,如果字符串的长度不相同,那么只能找到所有可能的字符串,再在s中去匹配,但是长度相同,就可以使用固定大小的滑动窗口来解决,只要连续出现的字符串能覆盖掉所有words,就是找到成功。 如何判断单词是否出现==>通过词频进行统计。
输入: 字符串 s,字符串数组 words
输出: words中所有字符的排列组合在s中开始的下标
条件: words中所有字符串的长度相同 1 <= s.length <= 10⁴
点击查看代码
func findSubstring(s string, words []string) []int { // 如果 words 为空,或者 s 的长度不足以容纳所有单词的组合,直接返回空结果 if len(words) == 0 || len(s) < len(words)*len(words[0]) { return []int{} } // 初始化 wordsCount,用于记录 words 中每个单词的频率 wordsCount := make(map[string]int) for _, word := range words { wordsCount[word]++ } wordLen := len(words[0]) // 单个单词的长度 totalWords := len(words) // 单词总数 res := []int{} // 存储结果的起始位置 // 通过不同的起点(i)遍历字符串,确保能检查所有可能的对齐方式 for i := 0; i < wordLen; i++ { left := i // 窗口的左边界,起始为当前起点 count := 0 // 记录当前窗口内匹配的单词数量 windowCount := make(map[string]int) // 记录窗口中单词的频率 // 移动右边界,步长为 wordLen,每次处理一个完整的单词 for right := i; right <= len(s)-wordLen; right += wordLen { word := s[right : right+wordLen] // 获取当前窗口中的单词 // 如果这个单词在 wordsCount 中,说明它是有效单词 if _, exists := wordsCount[word]; exists { windowCount[word]++ // 记录当前单词在窗口中的出现次数 count++ // 匹配单词数加 1 // 如果某个单词在窗口中的次数超过 words 中允许的次数,需要收缩窗口《也包括了找到符合的子串后》 for windowCount[word] > wordsCount[word] { leftWord := s[left : left+wordLen] // 窗口最左边的单词 windowCount[leftWord]-- // 窗口左边界的单词出现次数减 1 count-- // 匹配单词数减 1 left += wordLen // 左边界右移,缩小窗口 } // 如果窗口中单词的总数与 words 中单词总数相等,说明找到了一个匹配的子串 if count == totalWords { res = append(res, left) // 记录当前子串的起始位置 } } else { // 如果遇到无效单词,重置窗口,跳过当前单词 windowCount = make(map[string]int) count = 0 left = right + wordLen // 移动左边界到下一个单词的位置 } } } return res }
解法二:
依照题目的意思,先得到所有单词的排列组合,再将每个单词放入s中寻找是否存在。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~