zoukankan      html  css  js  c++  java
  • 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
        }
    }
    
  • 相关阅读:
    C++操作文件行(读取,删除,修改指定行)
    Windows注册表中修改UAC(用户账号控制)及批处理脚本
    Centos7.x 安装libevent2.x
    【Docker】:使用docker安装redis,挂载外部配置和数据
    【Docker】:使用docker安装mysql,挂载外部配置和数据
    开源定时任务框架Quartz(二)
    开源定时任务框架Quartz(一)
    Spring Boot系列教程十四:Spring boot同时支持HTTP和HTTPS
    数据结构与算法:单向链表实现与封装(有头)
    【C++札记】指针函数与函数指针
  • 原文地址:https://www.cnblogs.com/ganshuoos/p/13511102.html
Copyright © 2011-2022 走看看