zoukankan      html  css  js  c++  java
  • 【leetcode刷题笔记】Word Ladder II

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:

    1. Only one letter can be changed at a time
    2. Each intermediate word must exist in the dictionary

    For example,

    Given:
    start = "hit"
    end = "cog"
    dict = ["hot","dot","dog","lot","log"]

    Return

      [
        ["hit","hot","dot","dog","cog"],
        ["hit","hot","lot","log","cog"]
      ]

    Note:

    • All words have the same length.
    • All words contain only lowercase alphabetic characters.

    题解:算是leetcode最恶心的一道题了。

    Word Ladder一样要用BFS来搜索,但是要解决的问题是如何在BFS中保存路径。我们知道在DFS中 保存路径十分简单,但是在BFS中就很麻烦了。因为我们把点一层一层的放在队列里面,而不是一次把一条路径搜索完全。所以这里引进一种新的类Node如下:

    class Node{
            ArrayList<Node> prev;
            String me;
            int dist;
            public Node(String me,int dist){
                this.me = me;
                this.prev = null;
                this.dist = dist;
            }
        }

        使用该类,我们把搜索路径上遇到的每一个单词看成一个节点,me保存该节点对应的单词,dist保存从start单词搜索到该单词的最短距离,prev保存从start到该节点所有长度为dist的路径上该节点的前驱节点。

        这样我们就可以在完成BFS后,从最后一个节点endNode(endNode对应单词end),利用前驱节点信息DFS出startNode到endNode的所有路径了。函数findPath实现这个功能。

        另外在BFS的时候,我们需要一个map,来记录当前访问过哪些单词以及它们对应的节点。假设当前访问的节点是node,它对应的单词是t,我们通过修改t的每一位字母生成新的单词,如果新的单词在dict中且没有建立相应的节点(在map中没有记录),那么就建立相应的节点,并把该节点和单词的对应信息保存在map里面;如果当前生成的单词在dict中且已经有相应的节点,那么我们就看是否node也是它的前驱,如果是,把node加入它的前驱列表就可以了。

        结束的条件是,我们生成了一个单词,它正好等于end,说明找到了从start到end的一条路径(不过为了找到所有到end的路径,所以当前队列中的元素还是要遍历完,因为它们在同一层上,也有可能可以达到end,所以用一个stop变量控制最外层的大循环);或者队列为空,说明找不到从start到end的路径。

    最后代码如下:

     1 public class Solution {
     2 private List<List<String>> answer= new ArrayList<List<String>>();
     3     class Node{
     4         ArrayList<Node> prev;
     5         String me;
     6         int dist;
     7         public Node(String me,int dist){
     8             this.me = me;
     9             this.prev = null;
    10             this.dist = dist;
    11         }
    12     }
    13     private void findPath(Node endNode,ArrayList<String> result,String start){
    14         if(endNode.me.equals(start)){
    15             ArrayList<String> temp= new ArrayList<String>(result);
    16             answer.add(temp);
    17             return;
    18         }
    19         for(Node n:endNode.prev){
    20             result.add(0, n.me);
    21             findPath(n, result, start);
    22             result.remove(0);
    23         }
    24     }
    25     public List<List<String>> findLadders(String start, String end, Set<String> dict) {
    26         
    27         if(start == end){
    28             List<String> result = new ArrayList<String>();
    29             result.add(start);
    30             result.add(end);
    31             answer.add(result);
    32             return answer;
    33         }
    34         
    35         Queue<Node> queue = new LinkedList<Node>();
    36         HashMap<String, Node> map = new HashMap<String,Node>();
    37         
    38         Node startNdoe = new Node(start,0);
    39         queue.add(startNdoe);
    40         map.put(start, startNdoe);
    41         Node endNode = null;
    42         int strLen = start.length();
    43         boolean stop = false;
    44         
    45         while(!queue.isEmpty() && !stop){
    46             int thisLevel = queue.size();
    47             for(int i = 0;i < thisLevel;i++){
    48                 Node node = queue.poll();
    49                 for(int j = 0;j < strLen;j++){
    50                     StringBuilder t = new StringBuilder(node.me);
    51                     char ch_t = node.me.charAt(j);
    52                     for(char k = 'a';k <= 'z';k++){
    53                         if(k != ch_t){
    54                             t.setCharAt(j, k);
    55                             if(dict.contains(t.toString())){
    56                                 Node v = map.get(t.toString());
    57                                 if(v == null){
    58                                     Node tempNode = new Node(t.toString(),node.dist+1);
    59                                     tempNode.prev = new ArrayList<Node>();
    60                                     tempNode.prev.add(node);
    61                                     queue.add(tempNode);
    62                                     map.put(t.toString(), tempNode);
    63                                     if(t.toString().equals(end)){
    64                                         endNode = tempNode;
    65                                         stop = true;
    66                                     }
    67                                 }
    68                                 else {
    69                                     if(v.dist == node.dist+1)
    70                                         v.prev.add(node);
    71                                 }
    72                             }
    73                         }
    74                     }
    75                 }
    76             }
    77         }
    78         if(endNode != null){
    79             ArrayList<String> result = new ArrayList<String>();
    80             result.add(endNode.me);
    81             findPath(endNode,result,start);
    82         }
    83         return answer;
    84     }
    85 }
  • 相关阅读:
    Linux内存分析
    mysql 分表
    安装YCM
    c/c++ 之静态库
    ubuntu20 宽带连接
    数据对齐
    计算机中浮点数的表示
    整数的表示
    信息的储存
    SparseTable ST表
  • 原文地址:https://www.cnblogs.com/sunshineatnoon/p/3871196.html
Copyright © 2011-2022 走看看