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;
        }
    }

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

  • 相关阅读:
    关于联想笔记本ThinkPad E470 没有外音 插耳机却有声音的解决办法
    Win10无法启动软件提示MSVCP110.dll丢失
    POJ-3984 迷宫问题(BFS找最短路径并保存)
    转圈游戏(简单的快速幂)
    统计一个整数的二进制中1的个数(暴力)
    手写哈希(实现简单的加数、查询)
    CodeForces
    L2-2 社交集群 (25 分)(一个写挫的并查集)
    7-4 交换二叉树中每个结点的左孩子和右孩子 (20 分)
    7-3 堆中的路径 (25 分)
  • 原文地址:https://www.cnblogs.com/airwindow/p/4220300.html
Copyright © 2011-2022 走看看