📑 题目:30. 串联所有单词的子串

🚀 本题 LeetCode 传送门

题目大意

给定一个源字符串 s,再给一个字符串数组,要求在源字符串中找到由字符串数组各种组合组成的连续串的起始下标,如果存在多个,在结果中都需要输出。

解题思路

这一题看似很难,但是有 2 个限定条件也导致这题不是特别难。1. 字符串数组里面的字符串长度都是一样的。2. 要求字符串数组中的字符串都要连续连在一起的,前后顺序可以是任意排列组合。

解题思路,先将字符串数组里面的所有字符串都存到 map 中,并累计出现的次数。然后从源字符串从头开始扫,每次判断字符串数组里面的字符串时候全部都用完了(计数是否为 0),如果全部都用完了,并且长度正好是字符串数组任意排列组合的总长度,就记录下这个组合的起始下标。如果不符合,就继续考察源字符串的下一个字符,直到扫完整个源字符串。

代码

  1. package leetcode
  2. func findSubstring(s string, words []string) []int {
  3. if len(words) == 0 {
  4. return []int{}
  5. }
  6. res := []int{}
  7. counter := map[string]int{}
  8. for _, w := range words {
  9. counter[w]++
  10. }
  11. length, totalLen, tmpCounter := len(words[0]), len(words[0])*len(words), copyMap(counter)
  12. for i, start := 0, 0; i < len(s)-length+1 && start < len(s)-length+1; i++ {
  13. //fmt.Printf(""sub = %v i = %v lenght = %v start = %v tmpCounter = %v totalLen = %v
  14. "", s[i:i+length], i, length, start, tmpCounter, totalLen)
  15. if tmpCounter[s[i:i+length]] > 0 {
  16. tmpCounter[s[i:i+length]]--
  17. //fmt.Printf(""******sub = %v i = %v lenght = %v start = %v tmpCounter = %v totalLen = %v
  18. "", s[i:i+length], i, length, start, tmpCounter, totalLen)
  19. if checkWords(tmpCounter) && (i+length-start == totalLen) {
  20. res = append(res, start)
  21. continue
  22. }
  23. i = i + length - 1
  24. } else {
  25. start++
  26. i = start - 1
  27. tmpCounter = copyMap(counter)
  28. }
  29. }
  30. return res
  31. }
  32. func checkWords(s map[string]int) bool {
  33. flag := true
  34. for _, v := range s {
  35. if v > 0 {
  36. flag = false
  37. break
  38. }
  39. }
  40. return flag
  41. }
  42. func copyMap(s map[string]int) map[string]int {
  43. c := map[string]int{}
  44. for k, v := range s {
  45. c[k] = v
  46. }
  47. return c
  48. }