zoukankan      html  css  js  c++  java
  • **Word Ladder

    Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWordto endWord, such that:

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

    For example,

    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.

    Note:

    • Return 0 if there is no such transformation sequence.
    • All words have the same length.
    • All words contain only lowercase alphabetic characters.

    思路: 

    LeetCode中为数不多的考图的难题。尽管题目看上去像字符串匹配题,但从“shortest transformation sequence from start to end”还是能透露出一点图论中最短路径题的味道。如何转化?

    1. 将每个单词看成图的一个节点。
    2. 当单词s1改变一个字符可以变成存在于字典的单词s2时,则s1与s2之间有连接。
    3. 给定s1和s2,问题I转化成了求在图中从s1->s2的最短路径长度。而问题II转化为了求所有s1->s2的最短路径。

    无论是求最短路径长度还是求所有最短路径,都是用BFS。在BFS中有三个关键步骤需要实现:

    1. 如何找到与当前节点相邻的所有节点。
    这里可以有两个策略:
    (1) 遍历整个字典,将其中每个单词与当前单词比较,判断是否只差一个字符。复杂度为:n*w,n为字典中的单词数量,w为单词长度。
    (2) 遍历当前单词的每个字符x,将其改变成a~z中除x外的任意一个,形成一个新的单词,在字典中判断是否存在。复杂度为:26*w,w为单词长度。
    这里可以和面试官讨论两种策略的取舍。对于通常的英语单词来说,长度大多小于100,而字典中的单词数则往往是成千上万,所以策略2相对较优。

    2. 如何标记一个节点已经被访问过,以避免重复访问。
    可以将访问过的单词从字典中删除。

    3. 一旦BFS找到目标单词,如何backtracking找回路径?

    解法一:

    public class Solution {
        public int ladderLength(String beginWord, String endWord, Set<String> wordList) 
        {
            if (wordList.size() == 0)  
                return 0; 
            Queue<String[]> queue = new LinkedList<String[]>();
            wordList.add(endWord);
            String[] pair = new String[2];
            int len = 1;
            pair[0] = beginWord;
            pair[1] = Integer.toString(len); //int to String
            queue.add(pair);
            while(!queue.isEmpty())
            {
                String[] top = queue.poll();
                String s = top[0];
                len = Integer.parseInt(top[1]);  //String to int
                if(s.equals(endWord))return len;
                ArrayList<String> neighbors = findNeighbors(s,wordList);
                for(int i=0;i<neighbors.size();i++)
                {
                    String[] temp = new String[2];
                    temp[0] = neighbors.get(i);
                    temp[1] = Integer.toString(len+1);
                    queue.add(temp);
                }
            }
            return 0;
        }
        
        public ArrayList<String> findNeighbors(String s, Set<String> wordList)
        {
            ArrayList<String> res = new ArrayList<String>();
            for(int i=0;i<s.length();i++)
            {
                char[] sChar = s.toCharArray();
                for(char c = 'a';c<'z';c++)
                {
                    sChar[i]=c;
                    String newWord = new String(sChar);
                    if(wordList.contains(newWord))
                    {
                        res.add(newWord);
                        wordList.remove(newWord);//删除掉遍历过的单词
                    }
                }
            }
            return res;
        }
    };

    解法二:用一个空的String名为tag来处理有多个可以走向的String的问题。

    public class Solution {
        public int ladderLength(String start, String end, Set<String> dict) {
            if (dict.size() == 0)  
                return 0; 
            LinkedList<String> queue = new LinkedList<String>();
            String tag = new String();
            queue.add(start);
            queue.add(tag);
            int len = 1;
            while(queue.size() > 1){
                String top = queue.pop();
                if(top == tag){
                    len++;
                    queue.add(tag);
                    continue;
                }
                if(top.equals(end)){
                    return len;
                }
                for(int i=0; i<top.length(); i++){
                    char[] currCharArr = top.toCharArray();
                    for(char c='a'; c<='z'; c++){
                        currCharArr[i] = c;
                        String newWord = new String(currCharArr);
                        if(dict.contains(newWord)){
                            queue.add(newWord);
                            dict.remove(newWord);//删除掉遍历过的单词
                        }
                    }
                }
            }
            return 0;
        }
    } 

    reference: http://bangbingsyb.blogspot.com/2014/11/leetcode-word-ladder-i-ii.html

  • 相关阅读:
    Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'kindergarten.n.stuMChkTime' which is not functionally dependent on columns in GROUP BY clause; this is in
    ajax上传图片报错TypeError: 'append' called on an object that does not implement interface Fo
    Error:(1, 1) java: 非法字符: 'ufeff'
    SSM项目启动报错WEB-INFlibjavax.servlet-api-4.0.1.jar)
    SSH项目中使用struts-tags报错According to TLD or attribute directive in tag file, attribute test does not accept any expressions
    java查询数据库数据时报错antlr/ANTLRException
    [React Testing] Mock HTTP Requests with jest.mock in React Component Tests
    [React ARIA Testing] Test Accessibility of Rendered React Components with jest-axe
    [React Testing] Assert That Something is NOT Rendered with React Testing Library (with rerender & query)
    [React Testing] Improve Test Confidence with the User Event Module
  • 原文地址:https://www.cnblogs.com/hygeia/p/5133137.html
Copyright © 2011-2022 走看看