[LeetCode]Word Ladder,解题报告

目录


题目

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.

思路

这道题目本身不难,但是很考察每个做题人的抽象能力。因为之前我在《编程之美》上看到过这个题目,所以我很快的能把这道题跟多叉树联系在一起。

我们假设start字符串为多叉树的根节点,end字符串为多叉树最后的叶子节点。那当start字符串改变其中一个字符形成的新字符串new,并且new属于dict字典当中,那new字符串就是start的第一个子节点。其他节点以此类推。

当我们把这道题目想成一个多叉树之后,接下来我们要做的就是从根节点开始,找一条能走到end节点的路径。遍历的方法有:BFS和DFS,从时间角度考虑,我们当然选择BFS。


AC代码

有人在明白了抽象成多叉树之后,依然可能面临TLE的问题。

原因:通常我们入队列的方式是从dict字典里选一个字符串,判断和当前字符串是否相差一个字符,是则入队列,不是,则不入队列。这样的时间复杂度是O(n),n是字典的数量。当n很大时,就容易TLE。

解决方案:我们可以换一种思路,英文字母一共26个,当前字符串的长度是L,所以我们用26个英文字母对当前字符串的每个字符挨个替换,看形成的新字符串是否在字典中。是则入队列,不是则不入队列。这样的时间复杂度是:O(L* 26)。这样亲测,不超时。

public class Solution {
    public static int ladderLength(String start, String end, Set<String> dict) {
        int dist = calDistance(start, end);
        if (dist == 1) {
            return 2;
        }

        return bfsDict(dict, start, end);
    }

    private static int calDistance(String word1, String word2) {
        int dist = 0;

        for (int i = 0; i < word1.length(); i++) {
            if (word1.charAt(i) != word2.charAt(i)) {
                dist += 1;
            }
        }

        return dist;
    }

    private static void enQueue(Set<String> dict, LinkedList<String> queue, String target, Map<String, Integer> map, int step) {
        if (dict == null || dict.isEmpty()) {
            return;
        }

        for (int i = 0; i < target.length(); i++) {
            for (char c = 'a'; c <= 'z'; c++) {
                StringBuilder sBuilder = new StringBuilder(target);
                if (sBuilder.charAt(i) == c) {
                    continue;
                }
                sBuilder.setCharAt(i, c);
                if (dict.contains(sBuilder.toString())) {
                    queue.addLast(sBuilder.toString());
                    dict.remove(sBuilder.toString());
                    map.put(sBuilder.toString(), step + 1);
                }
            }
        }
    }

    private static int bfsDict(Set<String> dict, String start, String end) {
        LinkedList<String> queue = new LinkedList<String>();
        Map<String, Integer> hashMap = new HashMap<String, Integer>();
        enQueue(dict, queue, start, hashMap, 1);

        while (!queue.isEmpty()) {
            String word = queue.poll();
            int step = hashMap.get(word);
            if (calDistance(word, end) == 1) {
                return step + 1;
            }

            enQueue(dict, queue, word, hashMap, step);
        }

        return 0;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值