Leetcode 126 WordLadder2 笔记

161 阅读2分钟

WordLadder2

Hard

  • 将wordList里面的元素放到Set dict()里,查找时间可以优化至O(1), 很简单的代码
Set<String> dict = new HashSet<>(wordList);
  • 一个单词(String)可以转化成什么其他的单词(List)-> 映射关系
  • 过程中的映射关系, 用HashMap表示
  • 用BFS去填充map,把所有情况走一遍
  • tmp set 用来更新 start set
  • 把startSet里单词从dict里删除,所有开始的单词都不会再用到
  • 修改String中的单独字母,转化为 charArray()
for(String s : startSet){
    char[] chs = s.toCharArray();
    ...
}
  • 修改完将新单词存在一个新String word里, 这样可以保证原来的String 是不变, 便于之后的back tracking
String word = new String(chs);
  • 验证在dict里的新单词: 如果是endWord - 结束; 如果不是 - 放入tmp中, 作为下一次进入BFS的startSet
  • 如果s不在map就先添加key和空value - (new ArrayList()) 之后把变化出来的新单词加到arrayList里
  • 把一个单词的一位,从a-z改完一遍后,记得把这位还原回原来的字母
  • 用DFS去生成结果
  • base case: word 等于 endWord 结果加上deep copy的单词list,deep copy原因是list是reference, 会随着后面的back tracking不断变化
  • 或者 map里当前word没有value, 意味着没有可演变的单词, 又不等于endWord,只能 return
  • DFS主体: 循环每个map value 的 list 中的每个单词, 每个单词再找它们对应的value
  • 删除最后一个元素:在backtacking向上回溯的时候,需要一步一步地删除以前加入的元素,如果没有这一句的话,那么上一条路径的solution也会一直保存在solution中(来源:blog.csdn.net/shenzhu0127…

代码

class Solution {
    public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
        List<List<String>> res = new ArrayList<>();
        Set<String> dict = new HashSet<>(wordList);
        if(!dict.contains(endWord))
            return res;
        
        Map<String, List<String>> map = new HashMap<>();
        Set<String> startSet = new HashSet<>();
        startSet.add(beginWord);
        bfs(startSet, endWord, map, dict);
        
        List<String> list = new ArrayList<>();
        list.add(beginWord);
        dfs(res, list, endWord, beginWord, map);
        
        return res;
    }
    
    private void dfs(List<List<String>> res, List<String> list, String endWord, String word, Map<String, List<String>> map){
        if(word.equals(endWord)){
            res.add(new ArrayList(list));
            return;
        }
        if(map.get(word) == null) return;
        
        for(String s : map.get(word)){
            list.add(s);
            dfs(res, list, endWord, s, map);
            list.remove(list.size() - 1);
        }
    }
    
    private void bfs(Set<String> startSet, String endWord, Map<String, List<String>> map, Set<String> dict){
        if(startSet.size() == 0) return;
        
        Set<String> tmp = new HashSet<>();
        boolean finish = false;
        dict.removeAll(startSet);
        
        for(String s : startSet){
            char[] chs = s.toCharArray();
            for(int i = 0; i < chs.length; i++){
                char old = chs[i];
                for(char c = 'a'; c <= 'z'; c++){
                    chs[i] = c;
                    String word = new String(chs);
                    if(dict.contains(word)){
                        if(endWord.equals(word)){
                            finish = true;
                        }else{
                            tmp.add(word);
                        }
                        
                        if(map.get(s) == null){
                            map.put(s, new ArrayList<>());
                        }
                        map.get(s).add(word);
                    }
                }
                chs[i] = old;
            }
        }
        
        if(!finish){
            bfs(tmp, endWord, map, dict);
        }
        
    }
    
}

BFS, DFS, back tracking, HashMap