关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

LeetCode - #30 串联所有单词的子串(Top 100)

发布时间:2023-06-28 19:00:31

前言

本题为 LeetCode 前 100 高频题

本题由于没有合适答案为以往遗留问题,最近有时间将以往遗留问题一一完善。

我们社区陆续会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。

LeetCode 算法到目前我们已经更新到 29 期,我们会保持更新时间和进度(周一、周三、周五早上 9:00 发布),每期的内容不多,我们希望大家可以在上班路上阅读,长久积累会有很大提升。

不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。

难度水平:困难

1. 描述

给定一个字符串 s 和一个字符串数组 wordswords 中所有字符串 长度相同

s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。

例如,如果 words = ["ab","cd","ef"], 那么 "abcdef""abefcd""cdabef""cdefab""efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。
返回所有串联字串在 s 中的开始索引。你可以以 任意顺序 返回答案。

2. 示例

示例 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 由小写英文字母组成

3. 答案

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 基础为核心的技术内容,也整理收集优秀的学习资料。


/template/Home/leiyu/PC/Static