1

题目要求

Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

Only one letter can be changed at a time
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
Return
  [
    ["hit","hot","dot","dog","cog"],
    ["hit","hot","lot","log","cog"]
  ]
Note:
Return an empty list if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.
You may assume no duplicates in the word list.
Yo

u may assume beginWord and endWord are non-empty and are not the same.

相比于Word Ladder I,II要求返回所有的最短路径。

思路与代码

在继续往下看之前,请先参考I的这篇博客
首先我们再来查看一下题目中的例子。其实我们可以将路径化为有向图,然后将有向图中从beginWord至endWord的最短路径全部枚举出来。这里需要考虑最合适的数据结构。graph的话我们通过Map<String,List<String>>来记录节点和从该节点出发可以到达的其它节点。在题中的含义也就是s1所能转换的所有s2。至于如何生成该有向图,则需要通过广度优先算法,利用队列来实现。将每一层的string分别入栈。如果遇到endWord则至该层结尾广度优先算法结束。

这里有一个可以提高的计算效率的数据结构。在一开始,我通过一个list来记录所有上层已经遍历过的string。通过这种方式来防止形成圈。但是这样的形式造成的代码的超时,所以换成了Map<String, Integer>来记录String的最低层数。

    public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
        
        Map<String, Integer> ladder = new HashMap<String, Integer>();
        for(int i = 0 ; i<wordList.size() ; i++){
            ladder.put(wordList.get(i), Integer.MAX_VALUE);
        }
        ladder.put(beginWord, 0);
        Queue<String> q = new LinkedList<String>();
        int minStep = Integer.MAX_VALUE;
        if(beginWord!=null){
            q.offer(beginWord);
            while(!q.isEmpty()){
                String current = q.poll();
                int step = ladder.get(current)+1;
                if(step>minStep) break;
                for (int i = 0; i < current.length(); i++){
                    StringBuilder sb = new StringBuilder(current);
                    for (char ch='a';  ch <= 'z'; ch++){
                        sb.setCharAt(i, ch);
                        String sbs = sb.toString();
                        if(ladder.containsKey(sbs)){
                            if(step>ladder.get(sbs)) continue;
                            else if(step<ladder.get(sbs)){
                                q.add(sbs);
                                ladder.put(sbs, step);
                            }
                            if(map.containsKey(current)){
                                map.get(current).add(sbs);
                            }else{
                                Set<String> list= new HashSet<String>();
                                list.add(sbs);
                                map.put(current,list);
                            }
                            if(sbs.equals(endWord)) minStep = step;
                        }
                    }
                }
            }
        }
        
        generatePath(beginWord, endWord, new ArrayList<String>());
        return result;
    }
    public void generatePath(String currentWord, String endWord, List<String> current){
        current.add(currentWord);
        if(currentWord.equals(endWord)){
            result.add(new ArrayList<String>(current));
        }else{
            Set<String> set = map.get(currentWord);
            if(set!=null){
                for(String s : set){
                    generatePath(s, endWord,current);
                }    
            }    
        }
        current.remove(current.size()-1);
    }

clipboard.png
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~


raledong
2.7k 声望2k 粉丝

心怀远方,负重前行