zoukankan      html  css  js  c++  java
  • 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;
        }
    }
  • 相关阅读:
    MyString
    Django疑难问题
    mysql 疑难问题-django
    python时间转换 ticks-FYI
    django建议入门-FYI
    Python风格规范-FYI
    scrum敏捷开发☞
    git基本命令
    centos下的安装mysql,jdk
    memcached for .net on windows
  • 原文地址:https://www.cnblogs.com/hujunzheng/p/7327101.html
Copyright © 2011-2022 走看看