LeetCode 刷题【126. 单词接龙 II】

126. 单词接龙 II

自己做

解:递归选取(超时)

java 复制代码
class Solution {
    private int min_len = Integer.MAX_VALUE;
    private List<Boolean> choice;                       //标记是否选取
    private List<List<String>> res;                     //存在结果

    public void searchWord(String endWord, List<String> wordList, List<Boolean> option, List<String> combine){
        if(combine.size() > min_len)                            //比最短组合长也没必要继续往下延伸了
            return;
        
        List<String> combination = new ArrayList(combine);      
        List<Boolean> choice = new ArrayList(option);

        if(combination.get(combination.size() - 1).equals(endWord)){ //组合中最后一个元素和endWord相同即找到了对应组合
            if(res.size() == 0){                                //第一个组合,直接加入
                res.add(combination);
                min_len = combination.size();    
            }
            else{                                               //不是第一个组合,综合考虑
                if(combination.size() < min_len){               //找到了更短的序列,更新res
                    min_len = combination.size();
                    //清空以前的结果,以目前最短的为准
                    res = new ArrayList();
                    res.add(combination);
                }
                else if(combination.size() == min_len)          //找到了同样短的序列,加入res
                    res.add(combination);
                //比最短组合长的组合就不考虑了
            }
            return;
        }

        //选取这一层的元素
        for(int i = 0; i < wordList.size(); i++){
            if(!choice.get(i)){                                        //没有被选取过的元素
                //检查上个单词和当前单词不一样的字母数
                int num = 0;
                for(int j = 0; j < combination.get(combination.size() - 1).length(); j++)
                    if(wordList.get(i).charAt(j) != combination.get(combination.size() - 1).charAt(j))
                        num++;
                
                if(num == 1){                                          //相差一个字母,尝试选取
                    combination.add(wordList.get(i));
                    choice.set(i, true);
                    searchWord(endWord, wordList, choice, combination);           //放入组合
                    choice.set(i, false);
                    combination.remove(combination.size() - 1);
                }
                //除此之外都不选取
            }
        }
    }

    public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
        //检查endWord是否在wordList中
        boolean is_exist = false;
        choice = new ArrayList();       
        for(int i = 0; i < wordList.size(); i++){           //检查的同时顺便初始化choice
            if(endWord.equals(wordList.get(i)))              //存在
                is_exist = true;
            choice.add(false);
        }

        if(!is_exist)                                   //不存在就直接返回
            return new ArrayList();

        res = new ArrayList();
        List<String> combination = new ArrayList<String>();
        combination.add(beginWord);

        searchWord(endWord, wordList, choice, combination);

        return res;
    }
}

看题解

java 复制代码
class Solution {
    public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
        List<List<String>> res = new ArrayList<>();
        // 因为需要快速判断扩展出的单词是否在 wordList 里,因此需要将 wordList 存入哈希表,这里命名为「字典」
        Set<String> dict = new HashSet<>(wordList);
        // 特殊用例判断
        if (!dict.contains(endWord)) {
            return res;
        }

        dict.remove(beginWord);

        // 第 1 步:广度优先搜索建图
        // 记录扩展出的单词是在第几次扩展的时候得到的,key:单词,value:在广度优先搜索的第几层
        Map<String, Integer> steps = new HashMap<String, Integer>();
        steps.put(beginWord, 0);
        // 记录了单词是从哪些单词扩展而来,key:单词,value:单词列表,这些单词可以变换到 key ,它们是一对多关系
        Map<String, List<String>> from = new HashMap<String, List<String>>();
        int step = 1;
        boolean found = false;
        int wordLen = beginWord.length();
        Queue<String> queue = new ArrayDeque<String>();
        queue.offer(beginWord);
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                String currWord = queue.poll();
                char[] charArray = currWord.toCharArray();
                // 将每一位替换成 26 个小写英文字母
                for (int j = 0; j < wordLen; j++) {
                    char origin = charArray[j];
                    for (char c = 'a'; c <= 'z'; c++) {
                        charArray[j] = c;
                        String nextWord = String.valueOf(charArray);
                        if (steps.containsKey(nextWord) && step == steps.get(nextWord)) {
                            from.get(nextWord).add(currWord);
                        }
                        if (!dict.contains(nextWord)) {
                            continue;
                        }
                        // 如果从一个单词扩展出来的单词以前遍历过,距离一定更远,为了避免搜索到已经遍历到,且距离更远的单词,需要将它从 dict 中删除
                        dict.remove(nextWord);
                        // 这一层扩展出的单词进入队列
                        queue.offer(nextWord);

                        // 记录 nextWord 从 currWord 而来
                        from.putIfAbsent(nextWord, new ArrayList<>());
                        from.get(nextWord).add(currWord);
                        // 记录 nextWord 的 step
                        steps.put(nextWord, step);
                        if (nextWord.equals(endWord)) {
                            found = true;
                        }
                    }
                    charArray[j] = origin;
                }
            }
            step++;
            if (found) {
                break;
            }
        }

        // 第 2 步:回溯找到所有解,从 endWord 恢复到 beginWord ,所以每次尝试操作 path 列表的头部
        if (found) {
            Deque<String> path = new ArrayDeque<>();
            path.add(endWord);
            backtrack(from, path, beginWord, endWord, res);
        }
        return res;
    }

    public void backtrack(Map<String, List<String>> from, Deque<String> path, String beginWord, String cur, List<List<String>> res) {
        if (cur.equals(beginWord)) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (String precursor : from.get(cur)) {
            path.addFirst(precursor);
            backtrack(from, path, beginWord, precursor, res);
            path.removeFirst();
        }
    }
}、
相关推荐
铉铉这波能秀13 分钟前
LeetCode Hot100数据结构背景知识之字典(Dictionary)Python2026新版
数据结构·python·算法·leetcode·字典·dictionary
蜡笔小马22 分钟前
10.Boost.Geometry R-tree 空间索引详解
开发语言·c++·算法·r-tree
我是咸鱼不闲呀26 分钟前
力扣Hot100系列20(Java)——[动态规划]总结(下)( 单词拆分,最大递增子序列,乘积最大子数组 ,分割等和子集,最长有效括号)
java·leetcode·动态规划
唐梓航-求职中31 分钟前
编程-技术-算法-leetcode-288. 单词的唯一缩写
算法·leetcode·c#
仟濹32 分钟前
【算法打卡day3 | 2026-02-08 周日 | 算法: BFS】3_卡码网99_计数孤岛_BFS | 4_卡码网100_最大岛屿的面积DFS
算法·深度优先·宽度优先
Ll130452529836 分钟前
Leetcode二叉树part4
算法·leetcode·职场和发展
颜酱1 小时前
二叉树遍历思维实战
javascript·后端·算法
宝贝儿好1 小时前
第二章: 图像处理基本操作
算法
小陈phd1 小时前
多模态大模型学习笔记(二)——机器学习十大经典算法:一张表看懂分类 / 回归 / 聚类 / 降维
学习·算法·机器学习
@––––––1 小时前
力扣hot100—系列4-贪心算法
算法·leetcode·贪心算法