单词接龙(2)

题目描述

给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:

  1. 每次转换只能改变一个字母。
  2. 转换过程中的中间单词必须是字典中的单词。

说明:

  • 如果不存在这样的转换序列,返回一个空列表。
  • 所有单词具有相同的长度。
  • 所有单词只由小写字母组成。
  • 字典中不存在重复的单词。
  • 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。

示例1

输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

输出:
[
  ["hit","hot","dot","dog","cog"],
  ["hit","hot","lot","log","cog"]
]

示例2

输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

输出: []

解释: endWord "cog" 不在字典中,所以不存在符合要求的转换序列。

思路

双端BFS加简单DFS

实现

class Solution {
    public  List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
        //结果
        List<List<String>> res = new ArrayList<>();
        if(wordList == null) return res;
        //bfs搜索所用的字典
        Set<String> dicts = new HashSet<>(wordList);
        if(!dicts.contains(endWord)) return res;
        if(dicts.contains(beginWord)) dicts.remove(beginWord);
        //bfs搜索最短路径所用的开始和结束的字典
        Set<String> endList = new HashSet<>(),
                    beginList = new HashSet<>();
        //每个点所对应的邻接点,list
        Map<String, List<String>> map = new HashMap<>();
        beginList.add(beginWord);
        endList.add(endWord);
        bfs(map, beginList, endList, beginWord, endWord,dicts, false);   
        //dfs的前进路线保存list
        List<String> subList = new ArrayList<>();
        subList.add(beginWord); 
        dfs(map, res, subList, beginWord, endWord);
        return res;
    }
    void dfs (Map<String, List<String>> map, 
        List<List<String>> result, List<String> subList, 
        String beginWord, String endWord) {
        if(beginWord.equals(endWord)) {
          result.add(new ArrayList<>(subList));
          return; 
        }
        if (!map.containsKey(beginWord)) {
          return; 
        }
        for (String word : map.get(beginWord)) {
          subList.add(word);
          dfs(map, result, subList, word, endWord);
          subList.remove(subList.size() - 1);
        }
    }
    //reverse是双端bfs的一个优化
    void bfs(Map<String, List<String>> map, Set<String> beginList, Set<String> endList, String beginWord, String endWord,Set<String> wordList, boolean reverse){
        if(beginList.size() == 0) return;
        wordList.removeAll(beginList);
        boolean finish = false;
        Set<String> temp = new HashSet<>();
    	for(String str : beginList){
            char[] charr = str.toCharArray();
            for(int chI = 0; chI < charr.length; chI++){
                char old = charr[chI];
                for(char ch = 'a'; ch <= 'z'; ch++){
                    if(ch == old)
                        continue;
                    charr[chI] = ch;
                    String newstr = new String(charr);
                    if(!wordList.contains(newstr)){
                        continue;
                    }
                    //若是在某一层找到了最后的节点,就直接标记找到了,即一票决定。这里因为要找所有的最短路径,所以循环还是要继续的。
                    if(endList.contains(newstr)){
                        finish = true;
                    }else{
                        temp.add(newstr);
                    }
                    //无论怎么变换方向,永远用开始方向的字符做key,是为了后面的dfs,单一方向搜索
                    String key = reverse? newstr:str;
                    String value = reverse ? str : newstr;
                    if(!map.containsKey(key)){
                        map.put(key, new ArrayList<>());
                    }
                    map.get(key).add(value);

                }
                charr[chI] = old;
            }
        }
        if(!finish) {
            if(temp.size() > endList.size()){
                bfs(map, endList, temp, beginWord, endWord,wordList, !reverse);
            }else{
                bfs(map, temp, endList, beginWord, endWord, wordList, reverse);
            }
        }
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单词接龙一个游戏,旨在通过更改一个字母来逐步转换一个单词成为另一个定的单词。规则包括: 1. 可用于接龙单词字母必须与一个单词字母相同。 2. 当存在多个首字母相同的单词时,取长度最长的单词。如果长度也相等,则取词典序最小的单词。 3. 已经参与接龙单词不能重复使用。 对于给定的一组由小写字母组成的单词数组和定的起始单词和结束单词,我们需要进行单词接龙,并输出最长的单词串,其中单词串是由单词拼接而成,中间没有空格。如果不存在这样的转换序列,则返回0。 例如,对于输入的例子 beginWord = "hit",endWord = "cog",wordList = ["hot", "dot", "dog", "lot", "log"],我们可以进行以下单词接龙序列: "hit" -> "hot" -> "dot" -> "dog" -> "cog"。在这个例子中,最长的单词串为"hit" -> "hot" -> "dot" -> "dog" -> "cog"。 请注意,以上例子只是为了说明单词接龙的概念和规则,并不是针对Python编程的具体实现。具体的实现方法可以使用广度优先搜索 (BFS) 或双向BFS等算法来解决。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [python题目55:单词接龙](https://blog.csdn.net/m0_60741207/article/details/121528418)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [127. 单词接龙(Python)](https://blog.csdn.net/JulyLi2019/article/details/106610034)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值