lintcode120- Word Ladder- medium

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
 Notice
  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.

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.

 

public int ladderLength(String start, String end, Set<String> dict)

算法:层级遍历的BFS. 1.while循环每一层 2. for循环层内每一个单词 3.对每个单词都二重循环 length() * 26,试着把每个位置都试着换成a-z里的每一种。 对这每一种可能都判断符合最终要求没?合格就溜啦。虽然不合格但不重复的话就加入备胎queue下次再试后续可能性了。

数据结构:Queue + Set + int size + int steps

细节:1.注意每次换字母不是很功利地把最终目标string身上对应位置的字母拿过来换,而是要26个字母都试着换换,万一你可以经过dict里迂回的路径到达目标呢?  2.换字母方法有时间复杂度区分。用substring拼接要开辟四次,很花时间,string想+的时候尽量别+,用StringBuilder, sb.append, sb.toString。还有一种做法是先转char[],数组里替换了后再转回去new String (char[])。  3.小心一下start == end的corner case,这时候应该返回1。

 

public class Solution {
    /*
     * @param start: a string
     * @param end: a string
     * @param dict: a set of string
     * @return: An integer
     */
    public int ladderLength(String start, String end, Set<String> dict) {
        // write your code here
        if (dict == null || dict.size() == 0 || start == null || end == null || start.length() != end.length()) {
            return 0;
        }
        
        // 注意这个corner case
        if (start.equals(end)) {
            return 1;
        }
        
        Queue<String> queue = new LinkedList<String>();
        Set<String> set = new HashSet<String>();
        
        queue.offer(start);
        set.add(start);
        int steps = 2;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                String string = queue.poll();
                // 注意每次换字母不是只能换成end身上的!而是26个字母都可以换,不用那么功利直接往终点凑,可以往中间的词典词凑
                for (int idx = 0; idx < string.length(); idx++) {
                    for (char letter = 'a'; letter <= 'z'; letter++) {
                        // 注意如果用A写法替换字母的话,过不了时间复杂度,BC可以
                        // A) 
                        // String newStr =  string.substring(0,idx) + letter + string.substring(idx + 1, string.length());
                        // B) 
                        // char[] chars = string.toCharArray();
                        // chars[idx] = letter;
                        // String newStr = new String(chars);
                        // C)
                        StringBuilder sb = new StringBuilder();
                        sb.append(string.substring(0,idx));
                        sb.append(letter);
                        sb.append(string.substring(idx + 1, string.length()));
                        String newStr = sb.toString();
                        
                        if (newStr.equals(end)) {
                            return steps;
                        } else if (dict.contains(newStr) && !set.contains(newStr)) {
                            queue.offer(newStr);
                            set.add(newStr);
                        }
                    }
                }
            }
            steps++;
        }
        return 0;
    }
}

 

posted @ 2017-10-31 05:21  jasminemzy  阅读(186)  评论(0编辑  收藏  举报