BFS(三)单词接龙 ⅱ

对应 126. 单词接龙 II


问题描述

按字典 wordList 完成从单词 beginWord 到单词 endWord 转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> ... -> sk 这样的单词序列,并满足:

  • 每对相邻的单词之间仅有单个字母不同。
  • 转换过程中的每个单词 si(1 <= i <= k)必须是字典 wordList 中的单词。注意,beginWord 不必是字典 wordList 中的单词。
  • sk == endWord

给你两个单词 beginWord 和 endWord ,以及一个字典 wordList 。请你找出并返回所有从 beginWord 到 endWord 的 最短转换序列 ,如果不存在这样的转换序列,返回一个空列表。每个序列都应该以单词列表 [beginWord, s1, s2, ..., sk] 的形式返回。


解决思路

相比较于之前的 127.单词接龙,该问题需要在找到最短路径的基础上再找到所有的可行路径。一般的思路就是首先搜索一遍,找到可能存在的路径,再通过深度优先搜索找到所有的最短路径


实现

具体实现如下

class Solution {
    List<List<String>> ans = new ArrayList<>();
    Set<String> dict = new HashSet<>();

    public List<List<String>> findLadders(String s, String e, List<String> wl) {
        dict.addAll(wl);
        if (!dict.contains(e)) return ans;

        Map<String, Integer> steps = new HashMap<>();
        Map<String, List<String>> from = new HashMap<>(); // 记录每层出现的单词,方便之后的 DFS
        steps.put(s, 0);

        int step = 1;
        boolean found = false;
        int n = s.length();

        Deque<String> d = new LinkedList<>();
        d.offer(s);
        
        // 首先 BFS 找到可行的路径
        while (!d.isEmpty()) {
            int size = d.size();
            while (size-- > 0) {
                String curWord = d.poll();
                char[] array = curWord.toCharArray();
                for (int i = 0; i < n; ++i) {
                    char ch = array[i];
                    for (int j = 0; j < 26; ++j) {
                        array[i] = (char) ('a' + j);
                        String sub = String.valueOf(array);
                        if (steps.containsKey(sub) && step == steps.get(sub)) {
                            from.get(sub).add(curWord);
                        }
                        if (!dict.contains(sub)) continue;

                        dict.remove(sub);
                        d.offer(sub);

                        from.putIfAbsent(sub, new ArrayList<>());
                        from.get(sub).add(curWord);

                        steps.put(sub, step);
                        if (sub.equals(e)) found = true;
                    }
                    array[i] = ch;
                }
            }

            step++;
            if (found) break;
        }

        if (!found) return ans;
        
        // DFS 搜素所有的可行路径
        Deque<String> path = new ArrayDeque<>();
        path.add(e);
        dfs(path, from, e, s);

        return ans;
    }

    void dfs(Deque<String> path, Map<String, List<String>> from, String cur, String des) {
        if (cur.equals(des)) {
            ans.add(new ArrayList<>(path));
            return;
        }

        for (String prev : from.get(cur)) {
            path.offerFirst(prev);
            dfs(path, from, prev, des);
            path.pollFirst();
        }
    }
}

复杂度分析:略

posted @ 2021-12-16 17:13  FatalFlower  阅读(24)  评论(0编辑  收藏  举报