[Swift]LeetCode126. 单词接龙 II | Word Ladder II

Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

  1. Only one letter can be changed at a time
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

Note:

  • Return an empty list if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

Example 1:

Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
Output:
[
  ["hit","hot","dot","dog","cog"],
  ["hit","hot","lot","log","cog"]
]

Example 2:

Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Output: []
Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.

给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:

  1. 每次转换只能改变一个字母。
  2. 转换过程中的中间单词必须是字典中的单词。

说明:

  • 如果不存在这样的转换序列,返回一个空列表。
  • 所有单词具有相同的长度。
  • 所有单词只由小写字母组成。
  • 字典中不存在重复的单词。
  • 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。

示例 1:

输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
输出:
[
  ["hit","hot","dot","dog","cog"],
  ["hit","hot","lot","log","cog"]
]

示例 2:

输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
输出: []
解释: endWord "cog" 不在字典中,所以不存在符合要求的转换序列。

3640ms
 1 class Solution {
 2     let alphabet = Array("abcdefghijklmnopqrstuvwxyz")
 3 
 4     func findLadders(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> [[String]] {
 5         var dictionary = Set(wordList)
 6         var result = [[String]]()
 7         var distance = [String: Int]()
 8         var neighbors = [String: [String]]()
 9 
10         dictionary.insert(beginWord)
11 
12         // Get distances and neighbors for each word
13         bfs(beginWord, endWord, &dictionary, &distance, &neighbors)
14 
15         // Get results of word ledders
16         var temp = [String]()
17         dfs(beginWord, endWord, &dictionary, &distance, &neighbors, &result, &temp)
18 
19         return result
20     }
21 
22     private func bfs(_ beginWord: String, _ endWord: String, _ dictionary: inout Set<String>, _ distance: inout [String: Int], _ neighbors: inout [String: [String]]) {
23         for word in dictionary {
24             neighbors[word] = [String]()
25         }
26 
27         var queue = [String]()
28         queue.append(beginWord)
29         distance[beginWord] = 0
30 
31         while !queue.isEmpty {
32             var newQueue = [String]()
33             var foundEnd = false
34             for word in queue {
35                 let wordDistance = distance[word]!
36                 let wordNeighbors = getNeighbors(&dictionary, word)
37                 for neighbor in wordNeighbors {
38                     neighbors[word]!.append(neighbor)
39                     if distance[neighbor] == nil {
40                         distance[neighbor] = wordDistance + 1
41                         if neighbor == endWord {
42                             foundEnd = true
43                         } else {
44                             newQueue.append(neighbor)
45                         }
46                     }
47                 }
48             }
49             if foundEnd {
50                 break
51             }
52             queue = newQueue
53         }
54     }
55 
56     private func getNeighbors(_ dictionary: inout Set<String>, _ word: String) -> [String] {
57         var wordChars = Array(word)
58         var result = [String]()
59         for i in 0..<word.count {
60             let oldChar = wordChars[i]
61             for letter in alphabet {
62                 wordChars[i] = letter
63                 let newWord = String(wordChars)
64                 if dictionary.contains(newWord) {
65                     result.append(newWord)
66                 }
67             }
68             wordChars[i] = oldChar
69         }
70         return result
71     }
72 
73     private func dfs(_ beginWord: String, _ endWord: String, _ dictionary: inout Set<String>, _ distance: inout [String: Int], _ neighbors: inout [String: [String]], _ result: inout [[String]], _ temp: inout [String]) {
74         temp.append(beginWord)
75         if beginWord == endWord {
76             result.append(temp)
77         } else {
78             let wordDistance = distance[beginWord]!
79             for neighbor in neighbors[beginWord]! {
80                 if distance[neighbor]! == wordDistance + 1 {
81                     dfs(neighbor, endWord, &dictionary, &distance, &neighbors, &result, &temp)
82                 }
83             }
84         }
85         temp.removeLast()
86     }
87 }

4284ms

 1 class Solution {
 2     func findLadders(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> [[String]] {
 3         var res:[[String]] = [[String]]()
 4          //加速查找
 5         var dict:Set<String> = Set<String>(wordList)
 6         //构建队列
 7         var p:[String] = [String]()
 8         //加入源顶点
 9         p.append(beginWord)
10         var paths:[[String]] = [[String]]()
11         paths.append(p)
12         var level:Int = 1, minLevel:Int = Int.max
13         var words:Set<String> = Set<String>()
14         while (paths.count != 0)
15         {
16             var t = paths.removeFirst()
17             if t.count > level
18             {
19                 for w in words{dict.remove(w)}
20                 words = Set<String>()
21                 level = t.count
22                 if level > minLevel {break}
23             }
24             var last:String = t.last!
25             for i in 0..<last.count
26             {
27                 var newLast:String = last
28                 for ch in 97...122
29                 {
30                     newLast[i] = ch.ASCII
31                     if !dict.contains(newLast){continue}
32                     words.insert(newLast)
33                     var nextPath = t
34                     nextPath.append(newLast)
35                     if newLast == endWord
36                     {
37                         res.append(nextPath)
38                         minLevel = level
39                     }
40                     else
41                     {
42                         paths.append(nextPath)
43                     }
44                 }
45             }
46         }
47         return res
48     }
49 }
50 
51 //String扩展方法
52 extension String {
53     func toCharArray() -> [Character]
54     {
55         var arr:[Character] = [Character]()
56         for char in self.characters
57         {
58             arr.append(char)
59         }
60         return arr
61     }
62     
63     //subscript函数可以检索数组中的值
64     //直接按照索引方式截取指定索引的字符
65     subscript (_ i: Int) -> Character {
66         //读取字符
67         get {return self[index(startIndex, offsetBy: i)]}
68         
69         //修改字符
70         set
71         {
72             var str:String = self
73             var index = str.index(startIndex, offsetBy: i)
74             str.remove(at: index)
75             str.insert(newValue, at: index)
76             self = str
77         }
78     }
79 }
80 
81 //Int扩展方法  
82 extension Int
83 {
84     //属性:ASCII值(定义大写为字符值)
85     var ASCII:Character 
86     {
87         get {return Character(UnicodeScalar(self)!)}
88     }
89 }

猜你喜欢

转载自www.cnblogs.com/strengthen/p/9958336.html