• LeetCode -- Word Ladder


     问题描述:

    给定字典和一个起点单词、一个终点单词,每次只能变换一个字母,问从起点单词是否可以到达终点单词?最短多少步?

    Given:
    beginWord = "hit"
    endWord = "cog"
    wordList = ["hot","dot","dog","lot","log"]

    As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
    return its length 5.

    问题分析:

    (这个题目做的一肚子火,最后发现题目真的是有些问题,不太科学。本身思想是很好的,也很有意思的一个题目,但是由于该那乱七八糟的界定条件,浪费了很多时间。)

    主要思路如下:

    这是一个典型的隐式图的问题,对词典中的单词建立一个邻接表,每个单词可以怎么变换,然后用图的BFS找到一条最短路径就可以了。

    刚开始的时候的做法是,遍历字典的所有单词,看与当前的词之间是否可达。这种做法很直观,但是当字典的单词量巨大时就会TLE了,时间复杂度为O(N2)。

    因此正确的做法应该是:由于单词的长度肯定不会太长,所以我们对于单词的每个字母,从a-z依次改一下,看看改完的单词是否在词典中。由于词典使用Set存储的,而Java的set继承自HashSet,所以查找的时间复杂度为:O(logN).

     从起点单词开始,用队列存储,每次讲它的孩子放到队列中。注意这里记录的路径为遍历的层数,所以要用遍历存储一下层次的变化。

    (下面的代码依然没有通过所以测试,所以我选择了狗带。。。到网上找了一些解答的版本,依然没有试到成功的。。。先酱紫吧。以后再继续修正。。。。)

    Answer:

    public class Solution {
        public static int ladderLength(String beginWord, String endWord, Set<String> wordList) {
            if(wordList.contains(beginWord) && wordList.contains(endWord) 
                    && canGotoWord(beginWord, endWord) && wordList.size() == 2)
                    return 0;
            Queue<String> queue = new LinkedList<String>();
            Set<String> visited = new HashSet<String>();
            queue.add(beginWord);
            visited.add(beginWord);
            
            int step = 1;
            int cur = 1;
            int next = 0;
            while(!queue.isEmpty()) {
                    String word = queue.remove();
                    Set<String> child = getChild(word, wordList, visited, queue);
                    next = child.size();
                    
                    if(canGotoWord(word, endWord)) {
                        return ++step;
                    }
                    cur--;
                    if(cur == 0) {
                        step++;
                        cur = next;
                        next = 0;
                    }
                    
            }
            return step;
        }
        
        
        /**
         * get all of the child of one word. 
         * @param word
         * @param wordList
         * @param visited
         * @return
         */
        private static Set<String> getChild(String word, Set<String> wordList,
                Set<String> visited, Queue<String> q) {
            Set<String> child = new HashSet<String>();
            for(String w : wordList) {
                if(!visited.contains(w) && canGotoWord(word, w)) {
                    child.add(w);
                    visited.add(w);
                    q.add(w);
                }
            }
            return child;
        }
    
    
        /**
         * If the difference of w1 and w2 is 1, return true.
         * @param w1
         * @param w2
         * @return
         */
        private static boolean canGotoWord(String w1, String w2) {
            int count = 0;
            char[] ch1 = w1.toCharArray();
            char[] ch2 = w2.toCharArray();
            for(int i=0; i<ch1.length; i++) {
                if(ch1[i] != ch2[i])
                    count++;
            }
            if(count <= 1)
                return true;
            else 
                return false;
        }
    }

    可以AC的代码:

    用BFS遍历,然后每个节点记录当前的路径信息。

    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Set;
    
    class WordNode {
        String word;
        int depth;
        public WordNode(String word, int depth) {
            this.word = word;
            this.depth = depth;
        }
    }
    
    public class Solution {
        public int ladderLength(String begin, String end, Set<String> wordDict) {
            Queue<WordNode> queue =  new LinkedList<WordNode>();
            queue.add(new WordNode(begin, 1));
            
            wordDict.add(end);
            while(!queue.isEmpty()) {
                WordNode top = queue.remove();
                
                if(top.word.equals(end))
                    return top.depth;
                
                //访问top节点的下一个节点
                char[] topCh = top.word.toCharArray();
                for(int i=0; i<topCh.length; i++) {
                    for(char c='a'; c<='z'; c++) {
                        char temp = topCh[i];
                        if(temp != c)
                            topCh[i] = c;
                        String newWord = new String(topCh);
                        if(wordDict.contains(newWord)) {
                            queue.add(new WordNode(newWord, top.depth+1));
                            wordDict.remove(newWord);
                        }
                        topCh[i] = temp;
                    }
                }
            }
            return 0;
            
        }
    }
  • 相关阅读:
    在openwrt上初体验PostgreSQL数据库
    Linux学习笔记(7)-系统资源查看
    Linux学习笔记(6)-工作管理
    Linux学习笔记(5)-进程管理
    Linux学习笔记(4)-文本编辑器vi的使用
    linux学习笔记(3)-文件系统
    Linux学习笔记(2)-用户和用户组
    linux学习笔记(1)-文件处理相关命令
    68.vivado与modelsim的关联以及器件库编译
    67.ARP协议
  • 原文地址:https://www.cnblogs.com/little-YTMM/p/5502954.html
Copyright © 2020-2023  润新知