LeetCode 25 Word Ladder II

Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) 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" ]

Return

[

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

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

]

NOTE: 

All words have the same length.

All words contain only lowercase alphabetic characters.

分析:

看到单词换字母,想到的是图,一个单词每换一个字母,就生成一个相邻节点,

看到最短路径,想到BFS,BFS可以确保搜索到的一定是最短路径

要输出最短路径,BFS之后就要从后往前原路返回,

要输出所有最短路径,则每一个节点要维护一个所有前驱节点的list,

要判断是不是前驱节点,则每一个节点要维护一个距离,

BFS的话,就要标记是否访问过,这个应该用个Hash,应为需要通过word访问node,所以应该用HashMap,

基于以上考虑,一个节点要保存所代表的word,要保存离开始节点的距离,要保存一个前驱节点的list.

感觉这个题信息量略大啊。。。

public class Solution {
    
    class Node{
        public int dist;
        public String str;
        public LinkedList<Node> prev;
        
        public Node(int dist, String str){
            this.dist = dist;
            this.str = str;
            this.prev = new LinkedList<Node>();
        }
        
        public void addPrev(Node pNode){
            prev.add(pNode);
        }
    }
    
    public List<List<String>> findLadders(String start, String end, Set<String> dict) {
        //因为对dict里的word建立图关系,所以要把end加到字典里先
        dict.add(end);
        //Node可以存放更多信息,利用HashMap可以最快通过word访问到相对应的node
        Map<String, Node> map = new HashMap<String, Node>();
        //广度优先遍历当然用到队列
        Queue<String> queue = new LinkedList<String>();
        
        Node startNode = new Node(1, start);
        queue.offer(start);
        map.put(start, startNode);
        
        List<List<String>> ret = new ArrayList<List<String>>();
        //开始遍历
        while(!queue.isEmpty()){
            //出队当前节点
            String str = queue.poll();
            //找到了,开始生成路径,不需要再寻找下去
            if(str.equals(end)){
                getPaths(map.get(end), map, new ArrayList<String>(), ret);
                return ret;
            }
            //尝试str变体的所有可能,每一个位置都尝试所有26个字母
            for(int i=0; i<str.length(); i++){
                for(int j=0; j<26; j++){
                    //生成新的单词
                    String newStr = replace(str, i, (char)('a'+j));
                    //如果生成的新单词不再字典里,就不再考虑了
                    if(dict.contains(newStr)){
                        //在字典里,并且没有访问过
                        if(!map.containsKey(newStr)){
                            Node node = map.get(str);
                            //新建节点,距离比前驱加1
                            Node newNode = new Node(node.dist+1, newStr);
                            newNode.prev = new LinkedList<Node>();
                            //加入前驱节点
                            newNode.prev.add(node);
                            //建立Hash关系
                            map.put(newStr, newNode);
                            //入队,参加BFS
                            queue.offer(newStr);
                        }else{
                            //已经访问过,则要检查能不能建立图关系
                            Node node = map.get(newStr);
                            Node prevNode = map.get(str);
                            //如果满足距离关系,应该加一条边,即加入前驱list
                            if(node.dist == prevNode.dist+1){
                                node.addPrev(prevNode);
                            }
                        }
                    }
                }
            }
        }
        return ret;
    }
    //替换字符生成新单词的辅助函数
    private String replace(String str, int index, char c){
        StringBuilder sb = new StringBuilder(str);
        sb.setCharAt(index, c);
        return sb.toString();
    }
    //根据图关系,生成路径
    private void getPaths(Node end, Map<String, Node> map, ArrayList<String> curPath, List<List<String>> paths){
        if(end == null){
            paths.add(curPath);
            return;
        }
        curPath.add(0, end.str);
        if(!end.prev.isEmpty()){
            //递归
            for(Node prevNode : end.prev){
                //记住每一次都要重新new一个
                getPaths(prevNode, map, new ArrayList<String>(curPath), paths);
            }
        }else{
            getPaths(null, map, curPath, paths);
        }
    }
}



你可能感兴趣的:(hash,广度优先遍历,图算法,单词树)