首页 > 代码库 > lintcode 单词接龙II

lintcode 单词接龙II

题意

  给出两个单词(start和end)和一个字典,找出所有从start到end的最短转换序列

  比如:

    1、每次只能改变一个字母。

    2、变换过程中的中间单词必须在字典中出现。

注意事项

  • 所有单词具有相同的长度。
  • 所有单词都只包含小写字母。

样例

  给出数据如下:

  start = "hit"

  end = "cog"

  dict = ["hot","dot","dog","lot","log"]

  返回

  [

      ["hit","hot","dot","dog","cog"],

      ["hit","hot","lot","log","cog"]

    ]

 

解题思路

  根据每两个单词是否只差一个字母,进行建图,然后如下。

  1.深搜 + 回溯 + 记忆化(记录每个节点到 终结点 的最短转换序列),超时啦。。。

  2.通过广搜 计算出终结点到各个节点的最短距离(包括源节点到终结点的最短距离,也就是和 最短转换序列的长度对应)

public class Solution {    /**     * @param start, a string     * @param end,   a string     * @param dict,  a set of string     * @return a list of lists of string     */    public List<List<String>> findLadders(String start, String end, Set<String> dict) {        // write your code here        Map<String, List<String>> g = new HashMap<>();        Set<String> words = new HashSet<>(dict);        words.add(start);        words.add(end);        String[] wordArray = words.toArray(new String[0]);        for (int i = 0; i < wordArray.length - 1; ++i) {            for (int j = i + 1; j < wordArray.length; ++j) {                String first = wordArray[i], second = wordArray[j];                if (this.wordDiffCnt(first, second) == 1) {                    if (!g.containsKey(first)) {                        List<String> newList = new ArrayList<>();                        g.put(first, newList);                    }                    g.get(first).add(second);                    if (!g.containsKey(second)) {                        List<String> newList = new ArrayList<>();                        g.put(second, newList);                    }                    g.get(second).add(first);                }            }        }        resultMap = new HashMap<>();        visit = new HashSet<>();//      return dfs(g, start, end);//超时了,不知道怎么优化        List<List<String>> result = new ArrayList<>();        dist = new HashMap<>();        dfs(result, new LinkedList<String>(), g, start, end, bfs(g, end, start));        return result;    }    //通过bfs计算 终结点 到 源结点 的最短转换长度,以及 终结点到各个结点的最短距离(在通过 dfs寻找 最短转换序列的时候用到)    private Map<String, Integer> dist;    private int bfs(Map<String, List<String>> g, String start, String end) {        Queue<String> queue = new LinkedList<>();        visit.add(start);        queue.add(start);        dist.put(start, 1);        int minLen = 0;        while(!queue.isEmpty()) {            start = queue.poll();            if(start.equals(end)) {                if(minLen == 0) {                    minLen = dist.get(start);                }            }            if(g.containsKey(start)) {                for (String next : g.get(start)) {                    if(visit.contains(next)) continue;                    visit.add(next);                    queue.add(next);                    dist.put(next, dist.get(start)+1);                }            }        }        visit.clear();        return minLen;    }    private void dfs(List<List<String>> result, List<String> tmp, Map<String, List<String>> g, String start, String end, int minLen) {        if(tmp.size()+dist.get(start)-1 >= minLen) return;        if (start.equals(end)) {            result.add(new ArrayList<>(tmp));            result.get(result.size() - 1).add(end);            return;        }        visit.add(start);        tmp.add(start);        if (g.containsKey(start)) {            for (String next : g.get(start)) {                if(visit.contains(next)) continue;                dfs(result, tmp, g, next, end, minLen);            }        }        visit.remove(start);        tmp.remove(tmp.size()-1);    }    @Deprecated    private List<List<String>> dfs(Map<String, List<String>> g, String start, String end) {        List<List<String>> result = new ArrayList<>();        if (start.equals(end)) {            List<String> list = new ArrayList<>();            list.add(end);            result.add(list);            resultMap.put(end, result);            return result;        }        if (resultMap.containsKey(start)) {            return resultMap.get(start);        }        if (!g.containsKey(start)) {            resultMap.put(start, null);            return null;        }        visit.add(start);        List<List<String>> nextResult = new ArrayList<>();        int minLen = Integer.MAX_VALUE;        for (String next : g.get(start)) {            if(visit.contains(next)) continue;            List<List<String>> tmp = dfs(g, next, end);            if (tmp != null) {                for (List<String> list : tmp) {                    if(minLen > list.size()) minLen = list.size();                    nextResult.add(list);                }            }        }        visit.remove(start);        for (List<String> list : nextResult) {            if (list.size() == minLen) {                List<String> tmp = new LinkedList<>(list);                tmp.add(0, start);                result.add(tmp);            }        }        if(result.size() > 0) {            resultMap.put(start, result);        }        return result;    }    //记忆化搜索 每个节点到终点的最小步数的路径    private Map<String, List<List<String>>> resultMap;    //每个节点的访问的情况    private Set<String> visit;    private int wordDiffCnt(String s1, String s2) {        int diffCnt = 0;        for (int i = 0; i < s1.length(); ++i) {            if (s1.charAt(i) != s2.charAt(i)) {                ++diffCnt;            }        }        return diffCnt;    }}

 

 

 

lintcode 单词接龙II