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
    }
}
posted @ 2020-08-15 23:58  ganshuoos  阅读(120)  评论(0编辑  收藏  举报