本题为 LeetCode 前 100 高频题
本题由于没有合适答案为以往遗留问题,最近有时间将以往遗留问题一一完善。
我们社区陆续会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。
LeetCode 算法到目前我们已经更新到 29 期,我们会保持更新时间和进度(周一、周三、周五早上 9:00 发布),每期的内容不多,我们希望大家可以在上班路上阅读,长久积累会有很大提升。
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
难度水平:困难
给定一个字符串 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] 也是可以的。
示例 2
输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"] 输出:[] 解释:因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。 s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。 所以我们返回一个空数组。
示例 3
输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"] 输出:[6,9,12] 解释:因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。 子串 "foobarthe" 开始位置是 6。它是 words 中以 ["foo","bar","the"] 顺序排列的连接。 子串 "barthefoo" 开始位置是 9。它是 words 中以 ["bar","the","foo"] 顺序排列的连接。 子串 "thefoobar" 开始位置是 12。它是 words 中以 ["the","foo","bar"] 顺序排列的连接。
提示:
1 <= s.length <= 10^4
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i]
和 s
由小写英文字母组成func findSubstring(_ s: String, _ words: [String]) -> [Int] { if words.count == 0 { return [] } let perWord = words.first!.count if s.count < perWord * words.count { return [] } //找出所有words里面的单词作为key,个数作为value,存到字典里面 var wordsDic = [String: Int]() for word in words { let num = wordsDic[word] wordsDic[word] = (num ?? 0) + 1 } let chars = Array(s) //存放结果的数组 var result = [Int]() //遍历s字符串,创建新字典currentWordsDic存单词:个数。比较currentWordsDic和wordsDic个数 var i = 0 while i <= chars.count - perWord * words.count && i < perWord { var currentWordsDic = [String: Array<Int>]()//key:单词,value:数组index var startIndex = i var curIndex = startIndex while startIndex <= s.count - perWord * words.count { var curStr = "" for k in curIndex..<curIndex+perWord { curStr += String(chars[k]) } if (wordsDic[curStr] ?? 0) == 0 { //如果这个值不在原数组中 curIndex += perWord startIndex = curIndex currentWordsDic = [String: Array<Int>]()//key:单词,value:数组index }else { if (currentWordsDic[curStr] ?? []).count == 0 { currentWordsDic[curStr] = [curIndex] }else { currentWordsDic[curStr]!.append(curIndex) } if wordsDic[curStr]! - (currentWordsDic[curStr] ?? []).count < 0 { //如果这个值数量已经超出原数组,找出这个值的第一个index,并删除字典里面此index之前的数据,startIndex = 此index+3 let array = currentWordsDic[curStr]! let index = array.first! if index - startIndex < curIndex - (index + perWord) { for j in startIndex...index { var string = "" for k in j..<j+perWord { string += String(chars[k]) } currentWordsDic[string]!.removeFirst() } }else { currentWordsDic = [String: Array<Int>]()//key:单词,value:数组index for j in (index + perWord)...curIndex { var string = "" for k in j..<j+perWord { string += String(chars[k]) } if (currentWordsDic[string] ?? []).count == 0 { currentWordsDic[string] = [j] }else { currentWordsDic[string]!.append(j) } } } startIndex = index + perWord curIndex += perWord }else { if curIndex + perWord - startIndex == perWord * words.count { //如果遍历完数组,即找到了与数组单词适合的p子串 result.append(startIndex) var stringStart = "" for k in startIndex..<startIndex+perWord { stringStart += String(chars[k]) } currentWordsDic[stringStart]?.removeFirst() curIndex += perWord startIndex += perWord }else { curIndex += perWord } } } } i += 1 } return result}
点击前往 LeetCode 练习
我们是由 Swift 爱好者共同维护,我们会分享以 Swift 实战、SwiftUI、Swift 基础为核心的技术内容,也整理收集优秀的学习资料。
Copyright © 2023 leiyu.cn. All Rights Reserved. 磊宇云计算 版权所有 许可证编号:B1-20233142/B2-20230630 山东磊宇云计算有限公司 鲁ICP备2020045424号
磊宇云计算致力于以最 “绿色节能” 的方式,让每一位上云的客户成为全球绿色节能和降低碳排放的贡献者