• [Swift]LeetCode127. 单词接龙 | Word Ladder


    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址:https://www.cnblogs.com/strengthen/p/9957561.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence 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 0 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: 5
    
    Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
    return its length 5.
    

    Example 2:

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

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

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

    说明:

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

    示例 1:

    输入:
    beginWord = "hit",
    endWord = "cog",
    wordList = ["hot","dot","dog","lot","log","cog"]
    
    输出: 5
    
    解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",
         返回它的长度 5。
    

    示例 2:

    输入:
    beginWord = "hit"
    endWord = "cog"
    wordList = ["hot","dot","dog","lot","log"]
    
    输出: 0
    
    解释: endWord "cog" 不在字典中,所以无法进行转换。

    304ms
     1 class Solution {
     2     func ladderLength(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> Int {
     3         if !wordList.contains(endWord) 
     4         { 
     5             return 0 
     6         }
     7         
     8         let dict = Set(wordList)
     9         var beginSet = Set<String>()
    10         var endSet = Set<String>()
    11         var visitedSet = Set<String>()
    12         var length = 1
    13         var found = false
    14         
    15         beginSet.insert(beginWord)
    16         endSet.insert(endWord)
    17         
    18         while !found && !beginSet.isEmpty && !endSet.isEmpty {
    19             var nextSet = Set<String>()
    20             //accelerating search speed by swap begin and end
    21             if beginSet.count > endSet.count {
    22                 swap(&beginSet, &endSet)
    23             }
    24             found = helper(beginSet, endSet, dict, &visitedSet, &nextSet)
    25             beginSet = nextSet
    26             length += 1
    27         }
    28         return found ? length : 0
    29     }
    30     
    31     private func helper(_ beginSet: Set<String>, _ endSet: Set<String>, _ dict: Set<String>,
    32                         _ visitedSet: inout Set<String>, _ resSet: inout Set<String>) -> Bool {
    33         
    34         let alphaArray = Array("abcdefghijklmnopqrstuvwxyz")
    35         
    36         for word in beginSet {
    37             for i in 0 ..< word.count {
    38                 var chars = Array(word)
    39                 for j in 0 ..< alphaArray.count{
    40                     chars[i] = alphaArray[j]
    41                     let str = String(chars)
    42                     if dict.contains(str) {
    43                         if endSet.contains(str) 
    44                         { 
    45                             return true 
    46                         }
    47                         if !visitedSet.contains(str) 
    48                         { 
    49                             resSet.insert(str)
    50                             visitedSet.insert(str) 
    51                         }
    52                     }
    53                 }
    54             }
    55         }
    56         return false
    57     }
    58 }

    884ms

     1 class Solution {
     2     func ladderLength(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> Int {
     3         // ensure the endWord is in the wordList
     4         if !wordList.contains(endWord) {
     5             return 0
     6         }
     7 
     8         // build a word map with char array representations
     9         // this saves an enormous amount of time
    10         var wordMap: [String: [Character]] = [:]
    11         for i in 0..<wordList.count {
    12             // beginWord should never be in the list
    13             if wordList[i] == beginWord {
    14                 continue
    15             }
    16             wordMap[wordList[i]] = [Character](wordList[i].characters)
    17         }
    18         
    19         // we work the problem from the begining forward and end backwards
    20         // this allows us to deal with the smallest set of possibilities in 
    21         // both "directions"
    22         var beginMap:[String: [Character]] = [beginWord: [Character](beginWord.characters)]
    23         var endMap:[String: [Character]] = [endWord: [Character](endWord.characters)]
    24         
    25         // burnedMap bridges what has been used in both beginMap or endMap
    26         var burnedMap:[String: [Character]] = [:]
    27         
    28         // word len is stable throughout the iterations, pay for it only once
    29         let wordLen = beginWord.count
    30         
    31         // mutations tracts how many time mutated on the road from beginWord to endWord
    32         var mutations = 1
    33 
    34         // we continue while beginMap and endMap are non-empty
    35         // if one empties, there is no path from beginWord to endWord
    36         while !beginMap.isEmpty && !endMap.isEmpty {
    37             // minimize the working set by swapping in the smaller
    38             // set, we only care about the mutation count
    39             if beginMap.count > endMap.count {
    40                 let tempMap = beginMap
    41                 beginMap = endMap
    42                 endMap = tempMap
    43             }
    44 
    45             // track the upcoming set of mutation candidates we're about to create
    46             var newMap: [String: [Character]] = [:]
    47 
    48             // iterate throught he last set of mutation candidates
    49             for candidateKV in beginMap {
    50                 let candidateChars = candidateKV.value
    51                 
    52                 // walk through all the remaining (un-burned) valid words
    53                 for wordKV in wordMap {
    54                     let word = wordKV.key
    55                     let wordChars = wordKV.value
    56                     
    57                     // diff the candidate and valid words looking
    58                     // fir diffs of 1 character
    59                     var diffs = 0
    60                     
    61                     for i in 0..<wordLen {
    62                         if candidateChars[i] != wordChars[i] {
    63                             diffs += 1
    64                             if diffs > 1 {
    65                                 break
    66                             }
    67                         }
    68                     }
    69                     
    70                     // anything other than a diff of 1 is not applicable
    71                     // in this loop, we can only consider "word" if the
    72                     // diff is exactly 1
    73                     if diffs == 1 {
    74                         // we have a valid 1 character diff, use it
    75                         
    76                         if endMap[word] != nil {
    77                             // base case reached
    78                             return mutations + 1
    79                         }
    80                         
    81                         if burnedMap[word] == nil {
    82                             newMap[word] = wordChars
    83                             burnedMap[word] = wordChars
    84                         }
    85                     }
    86                 }
    87             }
    88             
    89             // we already evaluated what was in beginMap, we can 
    90             // lose those and use the newMap evaluation set 
    91             beginMap = newMap
    92             
    93             // we have completed an additional mutation step
    94             mutations += 1
    95         }
    96         
    97         return 0
    98     }
    99 }  

    1520ms

      1 class Solution {
      2     func ladderLength(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> Int {
      3         //Set类型替换数组类型,加速查找
      4         var wordSet:Set<String> = Set<String>(wordList)
      5         //构建队列,实现广度优先遍历
      6         var q:Queue<String> = Queue<String>()
      7         //加入源顶点
      8         q.enQueue(beginWord)
      9         var res:Int = 0
     10         while (!q.isEmpty())
     11         {
     12             for k in (1...q.count).reversed()
     13             {
     14                 var word:String = q.deQueue()!
     15                 if word == endWord {return res + 1}
     16                 for i in 0..<word.count
     17                 {
     18                     var newWord:String = word
     19                     for ch in 97...122
     20                     {
     21                         newWord[i] = ch.ASCII 
     22                         if wordSet.contains(newWord) && newWord != word
     23                         {
     24                             q.enQueue(newWord)
     25                             wordSet.remove(newWord)
     26                         }
     27                     }
     28                 }
     29             }
     30             res += 1
     31         }
     32          return 0
     33     }
     34 }
     35 
     36 //String扩展方法
     37 extension String {
     38     func toCharArray() -> [Character]
     39     {
     40         var arr:[Character] = [Character]()
     41         for char in self.characters
     42         {
     43             arr.append(char)
     44         }
     45         return arr
     46     }
     47     
     48     //subscript函数可以检索数组中的值
     49     //直接按照索引方式截取指定索引的字符
     50     subscript (_ i: Int) -> Character {
     51         //读取字符
     52         get {return self[index(startIndex, offsetBy: i)]}
     53         
     54         //修改字符
     55         set
     56         {
     57             var str:String = self
     58             var index = str.index(startIndex, offsetBy: i)
     59             str.remove(at: index)
     60             str.insert(newValue, at: index)
     61             self = str
     62         }
     63     }
     64 }
     65 
     66 //Int扩展方法  
     67 extension Int
     68 {
     69     //属性:ASCII值(定义大写为字符值)
     70     var ASCII:Character 
     71     {
     72         get {return Character(UnicodeScalar(self)!)}
     73     }
     74 }
     75 
     76 public struct Queue<T> {
     77     
     78     // 泛型数组:用于存储数据元素
     79     fileprivate var queue: [T] 
     80 
     81     // 返回队列中元素的个数
     82     public var count: Int {
     83         return queue.count
     84     }
     85     
     86     // 构造函数:创建一个空的队列
     87     public init() {
     88         queue = [T]()
     89     }
     90     
     91     //通过既定数组构造队列
     92     init(_ arr:[T]){
     93         queue = arr
     94     }
     95     
     96     // 检查队列是否为空
     97     // - returns: 如果队列为空,则返回true,否则返回false
     98     public func isEmpty() -> Bool {
     99         return queue.isEmpty
    100     }
    101     
    102     // 入队列操作:将元素添加到队列的末尾
    103     public mutating func enQueue(_ element: T) {
    104         queue.append(element)
    105     }
    106     
    107     // 出队列操作:删除并返回队列中的第一个元素
    108     public mutating func deQueue() -> T? {
    109         return queue.removeFirst()
    110     }
    111 }

    1692ms

     1 class Solution {
     2     func ladderLength(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> Int {
     3         
     4         var wordSet = Set(wordList)
     5         var level = 0
     6         var currentLevelWords = [beginWord]
     7         
     8         while !currentLevelWords.isEmpty {
     9             level += 1
    10             
    11             var nextLevelWords: [String] = []
    12             
    13             for word in currentLevelWords {
    14                 if word == endWord {
    15                     return level
    16                 }
    17                 
    18                 nextLevelWords += findRelatedWords(word: word, wordSet: &wordSet)
    19             }
    20             
    21             currentLevelWords = nextLevelWords
    22         }
    23         
    24         return 0
    25     }
    26     
    27     private let alphabet = Array("abcdefghijklmnopqrstuvwxyz")
    28     
    29     func findRelatedWords(word: String, wordSet: inout Set<String>) -> [String] {
    30         var relatedWords: [String] = []
    31         
    32         var word = word
    33         var wordIndex = word.startIndex
    34         while wordIndex < word.endIndex {
    35             
    36             let originalCharacter = word[wordIndex]
    37             
    38             for character in alphabet {
    39                 word.remove(at: wordIndex)
    40                 word.insert(character, at: wordIndex)
    41                 
    42                 if wordSet.contains(word) {
    43                     wordSet.remove(word)
    44                     
    45                     relatedWords.append(word)
    46                 }
    47             }
    48             
    49             word.remove(at: wordIndex)
    50             word.insert(originalCharacter, at: wordIndex)
    51             
    52             wordIndex = word.index(after: wordIndex)
    53         }
    54         
    55         return relatedWords
    56     }
    57 }

    1788ms

     1 class Solution {
     2     func ladderLength(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> Int {
     3         
     4         var wordSet = Set(wordList)
     5         var currentLevelWords = [beginWord]
     6         var level = 0
     7         
     8         while !currentLevelWords.isEmpty {
     9             level += 1
    10             
    11             var nextLevelWords: [String] = []
    12             
    13             for word in currentLevelWords {
    14                 
    15                 if word == endWord {
    16                     return level
    17                 }
    18                 
    19                 nextLevelWords += findCloseWords(word: word, wordSet: &wordSet)
    20             }
    21             
    22             currentLevelWords = nextLevelWords
    23         }
    24         
    25         return 0
    26     }
    27     
    28     let alphabet = Array("abcdefghijklmnopqrstuvwxyz")
    29     
    30     func findCloseWords(word: String, wordSet: inout Set<String>) -> [String] {
    31         
    32         var closeWords: [String] = []
    33         
    34         var word = word
    35         var wordIndex = word.startIndex
    36         
    37         while wordIndex < word.endIndex {
    38             
    39             let originalCharacter = word[wordIndex]
    40             
    41             for character in alphabet {
    42                 word.remove(at: wordIndex)
    43                 word.insert(character, at: wordIndex)
    44                 
    45                 if wordSet.contains(word) {
    46                     closeWords.append(word)
    47                     wordSet.remove(word)
    48                 }
    49             }
    50             
    51             word.remove(at: wordIndex)
    52             word.insert(originalCharacter, at: wordIndex)
    53             
    54             wordIndex = word.index(after: wordIndex)
    55         }
    56         
    57         return closeWords
    58     }
    59 }

    2284ms

     1 class Solution {
     2     func ladderLength(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> Int {
     3         var queue = [beginWord]
     4         var wordList = Set(wordList)
     5         var length = 1
     6 
     7         while !queue.isEmpty && !wordList.isEmpty {
     8             let count = queue.count
     9             for _ in 0..<count {
    10                 let word = queue.removeFirst()
    11 
    12                 let validTransforms = validTransformations(word, wordList)
    13                 for nextWord in validTransforms {
    14                     if nextWord == endWord {
    15                         return length + 1
    16                     }
    17                     wordList.remove(nextWord)
    18                     queue.append(nextWord)
    19                 }
    20             }
    21 
    22             length += 1
    23         }
    24 
    25         return 0
    26     }
    27     
    28     func validTransformations(_ word: String, _ wordList: Set<String>) -> [String] {
    29         var result = [String]()
    30         let alpahabetArray = Array("abcdefghijklmnopqrstuvwxyz".characters)
    31         for i in 0 ..< word.characters.count {
    32             var chars = Array(word.characters)
    33             for j in 0 ..< alpahabetArray.count {
    34                 chars[i] = alpahabetArray[j]
    35                 let newWord = String(chars)
    36                 if wordList.contains(newWord) {
    37                     result.append(newWord)
    38                 }
    39             }
    40         }
    41 
    42         return result
    43     }
    44 }

    3624ms

     1 class Solution {
     2     
     3     var letters = "abcdefghijklmnopqrstuvwxyz"
     4     func ladderLength(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> Int {
     5         // var map: [String:Set<String>] = [:]
     6         
     7         
     8         var wordSet = Set<String>(wordList)
     9         // wordSet.insert(endWord)
    10         var queue: [[String]] = [[beginWord]]
    11         var visited: Set<String> = []
    12         var ans = 1
    13         while !queue.isEmpty {
    14             var words = queue.removeLast()
    15             var construction: [String] = []
    16             for curr in words {
    17                 // print(curr)
    18                 if !visited.contains(curr) {
    19                     if curr == endWord {return ans}
    20                     var wordsToAdd = getWords(curr, wordSet)
    21                     // var wordsToAdd = Array(map[curr] ?? [])
    22                     construction.append(contentsOf: wordsToAdd)
    23                     visited.insert(curr)
    24                 }
    25             }
    26             if !construction.isEmpty {queue.insert(construction, at: 0)}
    27             ans += 1
    28         }
    29         return 0
    30     }
    31     
    32     func getWords(_ str1: String, _ validWords: Set<String>) -> [String] {
    33         var ans : [String] = []
    34         var strArr = Array(str1)
    35         var lettersArr = Array(letters)
    36         for i in 0..<str1.count {
    37             for j in 0..<lettersArr.count {
    38                 var temp = strArr[i]
    39                 strArr[i] = lettersArr[j]
    40                 var newStr = String(strArr)
    41                 if validWords.contains(newStr) {
    42                     ans.append(String(strArr))
    43                 }
    44                 strArr[i] = temp
    45             }
    46         }
    47         return ans
    48     }
    49     
    50     func isOneAway(_ str1: String, _ str2: String) -> Bool {
    51         var arr1 = Array(str1), arr2 = Array(str2)
    52         for i in 0..<arr1.count {
    53             if arr1[i] != arr2[i] {
    54                 arr1[i] = arr2[i]
    55                 return arr1 == arr2
    56             }
    57         }
    58         return false
    59     }
    60 }

    3984ms

     1 class Solution {
     2     func ladderLength(_ beginWord: String, _ endWord: String, _ wordList: [String]) -> Int {
     3         guard wordList.contains(endWord) else {
     4             return 0
     5         }
     6         
     7         var wordMap: [String: Int] = [:]
     8         for word in wordList {
     9             wordMap[word] = 1
    10         }
    11         
    12         var sequence: [String] = [beginWord]
    13         var map: [String: Int] = [beginWord : 1]
    14         let letters = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", 
    15                        "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
    16         
    17         while sequence.count > 0 {
    18             
    19             let bw = sequence.removeFirst()
    20             
    21             let level = map[bw]!
    22             
    23             let bws: [Character] = [Character](bw)
    24             for i in 0..<bws.count {
    25                 var chas = bws
    26                 for c in letters {
    27                     if bws[i] != Character(c) {
    28                         chas[i] = Character(c)
    29                         let word = String(chas)
    30                         
    31                         if word == endWord {
    32                             return level + 1
    33                         }
    34                         
    35                         if wordMap[word] != nil && map[word] == nil {
    36                             map[word] = level+1
    37                             sequence.append(word)
    38                         }
    39                     }
    40                 }
    41             }
    42         }
    43 
    44         return 0
    45     }
    46 }
  • 相关阅读:
    JAVAWE第一天
    01--2048实例开篇
    10--动作系统(四)动作类中的reverse方法
    09--动作系统(三)使用持续动作
    08--动作系统(二)使用即时动作
    【转】cocos2d-x windows开发环境配置
    07--动作系统(一)
    06--触摸事件响应
    05--简单场景切换与精灵创建
    04--简单菜单使用
  • 原文地址:https://www.cnblogs.com/strengthen/p/9957561.html
Copyright © 2020-2023  润新知