leetcode刷题笔记一百二十六题 单词接龙II
leetcode刷题笔记一百二十六题 单词接龙II
源地址:126. 单词接龙 II
问题描述:
给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:
每次转换只能改变一个字母。
转换后得到的单词必须是字典中的单词。
说明:如果不存在这样的转换序列,返回一个空列表。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 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" 不在字典中,所以不存在符合要求的转换序列。
import scala.collection.mutable
object Solution {
def findLadders(beginWord: String, endWord: String, wordList: List[String]): List[List[String]] = {
//构建参考字典
val wordSet = wordList.toSet
//
val prevMap = mutable.Map[String, List[String]]()
//邻居及其层次
val distance = mutable.HashMap[String, Int]()
val result = mutable.ListBuffer[List[String]]()
val list = mutable.ListBuffer[String]()
bfs(beginWord, endWord, wordSet, prevMap, distance)
generatePaths(prevMap.toMap, beginWord, endWord, list, result, distance.toMap)
result.map(_.reverse).toList
}
def bfs(beginWord:String, endWord: String, wordSet: Set[String], prevMap:mutable.Map[String, List[String]],distance: mutable.Map[String, Int]): Unit = {
//使用visited 标记已经访问过的邻居
val visited = mutable.Set[String]()
val queue = mutable.Queue[String]()
//初始化
queue.enqueue(beginWord)
distance.put(beginWord, 0)
//开始广度遍历
while (queue.isEmpty == false){
val word = queue.dequeue
if (visited.contains(word) == false){
//更新访问情况
visited.add(word)
//找到结果词
if (word == endWord) return
val neighbors = getNeighbors(word, wordSet)
//对neighbor进行处理
for (neighbor <- neighbors){
//排除访问过的neighbors
if (visited.contains(neighbor) == false) {
//未对当前neighbor层次确定
if (distance.contains(neighbor) == false) distance.put(neighbor, distance(word)+1)
queue.enqueue(neighbor)
//构建邻接表
val wordList = if (prevMap.contains(neighbor)) prevMap(neighbor)++List(word)
else List(word)
prevMap.put(neighbor, wordList)
}
}
}
}
}
def generatePaths(prevMap: Map[String, List[String]], beginWord: String, endWord: String, list: mutable.ListBuffer[String], result: mutable.ListBuffer[List[String]], distance:Map[String, Int]) : Unit = {
//回溯条件
if (endWord == beginWord) {
list.append(endWord)
result.append(list.toList)
list.remove(list.length -1)
return
}
if (prevMap.contains(endWord)){
list.append(endWord)
for (word <- prevMap(endWord)) {
//确定最短路径
if (distance(word) + 1 == distance(endWord)) generatePaths(prevMap, beginWord, word, list, result, distance)
}
list.remove(list.length -1)
}
}
def getNeighbors(word: String, wordSet: Set[String]):List[String] = {
val neighbors = mutable.ListBuffer[String]()
//针对输入word,对单词中的各个位置进行一位调换
word.zipWithIndex.foreach {
case (c, i) =>
val newCharArr = word.toCharArray
val temp = newCharArr(i)
for (ch <- 'a' to 'z') {
newCharArr(i) = ch
val newStr = newCharArr.mkString
//新构成的词汇在字典中出现过,且不是输入word
//将其加入neighbors
if (wordSet.contains(newStr) && ch != temp) neighbors += newStr
}
//还原
newCharArr(i) = temp
}
return neighbors.toList
}
}