126.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package main
  2. func findLadders(beginWord string, endWord string, wordList []string) (ladders [][]string) {
  3. endIdx, listLen := -1, len(wordList)
  4. for i := 0; i < listLen; i++ {
  5. if endWord == wordList[i] {
  6. endIdx = i
  7. break
  8. }
  9. }
  10. if endIdx == -1 {
  11. return
  12. } // Find end word in word list, if not found, return false
  13. adj := make([][]int, listLen)
  14. for i := 0; i < listLen; i++ {
  15. for j := i + 1; j < listLen; j++ {
  16. if isConvertible(wordList[i], wordList[j]) {
  17. adj[i] = append(adj[i], j) // Dont need to init each row of adj if use append
  18. adj[j] = append(adj[j], i)
  19. }
  20. }
  21. } // Create adj matrix
  22. visited := make([]bool, listLen)
  23. closest := make([]int, 0)
  24. distance := make([]int, listLen) // Distance from begin to word i
  25. prev := make([][]int, listLen) // List of prev point
  26. for i := 0; i < listLen; i++ {
  27. prev[i] = make([]int, 0)
  28. if isConvertible(beginWord, wordList[i]) {
  29. prev[i] = append(prev[i], -1) // -1 means begin word
  30. closest = append(closest, i)
  31. distance[i] = 1
  32. visited[i] = true
  33. }
  34. } // Init closest array
  35. for distance[endIdx] == 0 && len(closest) != 0 {
  36. newClosest := make([]int, 0)
  37. for _, c := range closest {
  38. for _, i := range adj[c] {
  39. if !visited[i] {
  40. if distance[i] == 0 {
  41. distance[i] = distance[c] + 1
  42. newClosest = append(newClosest, i)
  43. }
  44. prev[i] = append(prev[i], c)
  45. }
  46. }
  47. }
  48. for i := range newClosest {
  49. visited[newClosest[i]] = true
  50. }
  51. closest = newClosest
  52. }
  53. var getLadders func(int, []string) // Get ladders from prev path
  54. getLadders = func(idx int, ladder []string) {
  55. var newLadder []string
  56. if idx == -1 {
  57. newLadder = []string{beginWord}
  58. newLadder = append(newLadder, ladder...)
  59. ladders = append(ladders, newLadder)
  60. return
  61. }
  62. newLadder = []string{wordList[idx]}
  63. newLadder = append(newLadder, ladder...)
  64. for i := range prev[idx] {
  65. getLadders(prev[idx][i], newLadder)
  66. }
  67. }
  68. getLadders(endIdx, []string{})
  69. return
  70. }
  71. func isConvertible(a, b string) bool {
  72. diff := 0
  73. for i := range a {
  74. if a[i] != b[i] {
  75. diff++
  76. }
  77. if diff > 1 {
  78. return false
  79. }
  80. }
  81. return diff == 1
  82. }
  83. // func main() {
  84. // fmt.Println(findLadders(
  85. // "hit",
  86. // "cog",
  87. // []string{"hot", "dot", "dog", "lot", "log", "cog"}))
  88. // fmt.Println(findLadders(
  89. // "hit",
  90. // "cog",
  91. // []string{"hot", "dot", "dog", "lot", "log"}))
  92. // fmt.Println(findLadders(
  93. // "hot",
  94. // "dog",
  95. // []string{"hot", "dog", "dot"}))
  96. // }