zoukankan      html  css  js  c++  java
  • [LeetCode#127]Word Ladder

    ---恢复内容开始---

    The problem:

    Given two words (start and end), and a dictionary, find the length of shortest transformation sequence 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"]

    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.

    My analysis:

    This problem's solution is very elegant and tricky! It represents a new kind of problem that could be solved by using abstract graph. 
    The key idea: use the graph to search. But it differs a lot from the previous problem, which has a obvious link or neighbor list of a node. We need to extract this information from a very tricky way. 
    The abstract graph:
    1. represent each String in the dictionary as a node in the graph.
    2. iff two nodes differ in only one character, there is a edge between those two nodes in the graph.
    
    The shortest problem in the grpah:(unweighted graph)
    The breadth first search could layered the nodes in the graph. 
    The path from source node to another node in the breadth first traversal is the shortest path from source node to the node. The distance is the layer the node in. 
    
    It seems that there is no linkage domain, how could we traversal?
    Since we have no link to follow, how about we try all possible pathes according to the requirement!
    The requirement: Only one letter can be changed at a time. It is not hard to simulate. 
    for (int i = 0; i < cur.length(); i++) {
        char[] cur_array = cur.toCharArray();
        for (char c = 'a'; c <= 'z'; c++) {
            cur_array[i] = c;
            String temp = new String(cur_array);
        ...
    }
    However, the while loop could result in all possbile branches(which only differ a character with the current node). We could only search along the edge that existed in the graph, we need to rule out some unreasonable branches.
    if (dict.contains(temp) && !visited.contains(temp)) {
        queue.offer(temp);
        visited.add(temp);
        next_num++;
    }
    
    What a beautful way!!!(fake traversal and rule out!)
    
    Note:
    the above rountine is for continue search, which means we have not reach out the "end(target)" String. However, if we reach the target, we could directly return the distance, cause the target need not to be in the dict. 
    for (int i = 0; i < cur.length(); i++) {
        char[] cur_array = cur.toCharArray();
        for (char c = 'a'; c <= 'z'; c++) {
            cur_array[i] = c;
            String temp = new String(cur_array); 
            if (temp.equals(end))
                return level + 1;
        ...
        }
    }
    
    The time complexity analysis:
    while (!queue.isEmpty()) {
        ...
        for (int i = 0; i < cur.length(); i++) {
        ...
            for (char c = 'a'; c <= 'z'; c++) {
            ...
                if (dict.contains(temp) && !visited.contains(temp)) {
                    queue.offer(temp);
                    visited.add(temp);
                    next_num++;
                }
            }
        }
    }
    The time complexity for the big for loop: Length * 26
    Since we use "dict.contains(temp)" to restrict searching domain. we enter the for loop at most. dict.size() times. 
    thus the total complexity is 
    size(dict) * length * 26
    
    Note:
    Be very careful with the function of "!visited.contains(temp)".
    Unlike Binary, there could be circle in the graph, thus we must use visted set to record all nodes we have visited. Otherwise it would result in infinite loop. Cause we keep on(there might be iterleaves) enqueuing and dequeing it. 

    My solution:

    public class Solution {
        public int ladderLength(String start, String end, Set<String> dict) {
            
            if (start == null || end == null || dict == null || start.length() == 0 || end.length() == 0 || dict.size() == 0)
                return 0;
            
            HashSet<String> visited = new HashSet<String> ();
            Queue<String> queue= new LinkedList<String> ();
            String cur;
            
            queue.offer(start);
            int cur_num = 1;
            int next_num = 0;
            int level = 1;
            
            while (!queue.isEmpty()) {
                cur = queue.poll();
                cur_num-- ; //only intermdiate string need to be in the dict.
                for (int i = 0; i < cur.length(); i++) {
                    char[] cur_array = cur.toCharArray();
                    for (char c = 'a'; c <= 'z'; c++) {
                        cur_array[i] = c;
                        String temp = new String(cur_array); //must do it in this way, only change one char a time. 
                        if (temp.equals(end))
                            return level + 1;
                        if (dict.contains(temp) && !visited.contains(temp)) {//very imprtant checking condition!!!
                            queue.offer(temp);
                            visited.add(temp);
                            next_num++;
                        }
                    }
                }
                
                if (cur_num == 0) {
                    cur_num = next_num;
                    next_num = 0;
                    level++;
                }
            }
            return 0;
        }
    }

    ---恢复内容结束---

  • 相关阅读:
    笔记本Linux系统,修改合盖不待机
    用Java8把List转为Map
    获取本地请求的真实IP地址
    PowerDesigner 把Comment复制到name中和把name复制到Comment
    axios封装http请求
    Fiddler代理配置
    第十九章 代码重用
    第十八章 字符串
    第十七章 特殊类成员
    第十六章 多态性
  • 原文地址:https://www.cnblogs.com/airwindow/p/4220300.html
Copyright © 2011-2022 走看看