LeetCode题练习与总结:单词接龙Ⅱ--126

一、题目描述

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

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

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

示例 1:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出:[["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]
解释:存在 2 种最短的转换序列:
"hit" -> "hot" -> "dot" -> "dog" -> "cog"
"hit" -> "hot" -> "lot" -> "log" -> "cog"

示例 2:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出:[]
解释:endWord "cog" 不在字典 wordList 中,所以不存在符合要求的转换序列。

提示:

  • 1 <= beginWord.length <= 5
  • endWord.length == beginWord.length
  • 1 <= wordList.length <= 500
  • wordList[i].length == beginWord.length
  • beginWordendWord 和 wordList[i] 由小写英文字母组成
  • beginWord != endWord
  • wordList 中的所有单词 互不相同

二、解题思路

  1. 初始化:将beginWord添加到队列中,并设置其距离为0。初始化一个图graph来存储每个单词的相邻单词列表,和一个距离表distance来存储每个单词到beginWord的距离。

  2. 广度优先搜索:当队列不为空时,进行BFS。每次从队列中取出一个单词,并尝试将其每个位置的字母替换为’a’到’z’中的其他字母,生成新的单词。如果这个新单词在字典wordSet中且没有被访问过,或者已经被访问过但距离更短,则将其添加到队列中,并更新其距离和父节点。

  3. 找到最短路径:如果在BFS过程中找到了endWord,则标记找到并停止BFS。

  4. 回溯找到所有路径:如果找到了endWord,则从endWord开始回溯,通过父节点信息找到所有从beginWordendWord的最短路径,并将这些路径添加到结果列表中。

  5. 返回结果:如果找到了至少一条路径,则返回这些路径;如果没有找到,则返回空列表。

这个算法确保了只有最短路径会被考虑,因为它在找到endWord后停止了BFS,并且在回溯时只考虑了最短路径上的单词。这样可以避免生成和存储非最短路径,从而节省内存并提高效率。

三、具体代码

import java.util.*;public class Solution {public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {Set<String> wordSet = new HashSet<>(wordList);if (!wordSet.contains(endWord)) return new ArrayList<>();// 使用双向BFSMap<String, List<String>> graph = new HashMap<>();Map<String, Integer> distance = new HashMap<>();Queue<String> queue = new LinkedList<>();queue.add(beginWord);distance.put(beginWord, 0);boolean found = false;while (!queue.isEmpty()) {int level = distance.get(queue.peek());int size = queue.size();for (int i = 0; i < size; i++) {String current = queue.poll();char[] chars = current.toCharArray();for (int j = 0; j < chars.length; j++) {char original = chars[j];for (char c = 'a'; c <= 'z'; c++) {if (c == original) continue;chars[j] = c;String newWord = new String(chars);if (distance.containsKey(newWord) && distance.get(newWord) == level + 1) {graph.computeIfAbsent(newWord, k -> new ArrayList<>()).add(current);} else if (!distance.containsKey(newWord) && wordSet.contains(newWord)) {distance.put(newWord, level + 1);queue.add(newWord);graph.computeIfAbsent(newWord, k -> new ArrayList<>()).add(current);}}chars[j] = original;}}if (distance.containsKey(endWord)) {found = true;break;}}// 如果没有找到endWord,返回空列表if (!found) return new ArrayList<>();// 回溯找到所有路径List<List<String>> result = new ArrayList<>();List<String> path = new ArrayList<>();path.add(endWord);backtrack(graph, endWord, beginWord, path, result);return result;}private void backtrack(Map<String, List<String>> graph, String current, String beginWord, List<String> path, List<List<String>> result) {if (current.equals(beginWord)) {Collections.reverse(path);result.add(new ArrayList<>(path));Collections.reverse(path);return;}if (!graph.containsKey(current)) return;for (String next : graph.get(current)) {path.add(next);backtrack(graph, next, beginWord, path, result);path.remove(path.size() - 1);}}
}

四、时间复杂度和空间复杂度

1. 时间复杂度

  • 构建图的时间复杂度:对于每个单词,我们需要检查其所有可能的邻居(即通过改变每个位置的字母),共有wordList.size()个单词,每个单词有wordLength个字母,因此时间复杂度为O(wordList.size() * wordLength * 26),因为字母表有26个字母。
  • BFS的时间复杂度:在最坏情况下,我们需要访问图中的每个节点,并且对于每个节点,我们可能需要检查其所有邻居。因此,时间复杂度为O(V + E),其中V是节点数,E是边数。在这个问题中,V最大为wordList.size()E最大为wordList.size() * wordLength * 26(每个单词都有可能与其他所有单词相连)。
  • 回溯的时间复杂度:在最坏情况下,我们需要回溯所有从beginWordendWord的路径。每条路径的长度为pathLength,因此时间复杂度为O(pathLength * numPaths),其中numPaths是最短路径的数量。
  • 综合以上,总的时间复杂度O(wordList.size() * wordLength * 26 + wordList.size() * wordLength * 26 + pathLength * numPaths)

2. 空间复杂度

  • 图的空间复杂度:我们需要存储每个单词的邻居列表,因此空间复杂度为O(wordList.size() * wordLength * 26)
  • BFS队列的空间复杂度:在队列中,我们最多可能存储所有的单词,因此空间复杂度为O(wordList.size())
  • 距离表和路径列表的空间复杂度:这两个数据结构的空间复杂度也是O(wordList.size())
  • 回溯过程中的路径列表空间复杂度:在回溯过程中,我们为每条路径维护一个列表,因此空间复杂度为O(pathLength * numPaths)

在实际应用中,由于每个单词的邻居数量通常远小于26个,因此实际的时间和空间复杂度可能会低于上述分析的上限。此外,由于BFS在找到最短路径后会停止,回溯过程中只考虑最短路径,这也会降低实际的时间和空间复杂度。

五、总结知识点

  1. 广度优先搜索(BFS):这是一种图遍历算法,用于从起点开始搜索最近的节点。在这个问题中,我们使用BFS来找到从beginWordendWord的最短转换序列。

  2. 双向BFS:这是一种优化的BFS,从起点和终点同时进行搜索,直到两者相遇。这样可以减少搜索空间,提高效率。

  3. 图的表示:我们使用一个哈希表graph来表示图,其中键是单词,值是与其相邻的单词列表。

  4. 哈希集合Set:用于存储wordList中的单词,以便快速判断一个单词是否在字典中。

  5. 队列Queue:用于在BFS中存储待访问的节点。

  6. 回溯算法:这是一种递归算法,用于从终点回溯到起点,找到所有可能的转换序列。

  7. 列表List和数组ArrayList:用于存储路径和单词的邻居。

  8. 字符数组和字符串操作:在代码中,我们使用了字符数组来表示单词,并通过改变字符数组中的字符来生成新的单词。

  9. Java中的char类型和字符遍历:代码中使用了char类型来表示字母,并通过循环遍历az来尝试所有可能的字符替换。

  10. Java中的MapSet的操作:代码中使用了MapSetcontainsKeyputcomputeIfAbsent等方法来进行图的操作和单词的查找。

  11. Java中的Collections:用于操作集合,如reverse方法用于反转列表。

  12. 递归函数backtrack函数是一个递归函数,用于回溯找到所有可能的转换序列。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/27106.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于PSO粒子群优化的CNN-LSTM的时间序列回归预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 卷积神经网络&#xff08;CNN&#xff09; 4.2 长短期记忆网络&#xff08;LSTM&#xff09; 4.3 CNN-LSTM结合PSO的时间序列预测 5.算法完整程序工程 1.算法运行效果图预览 2.算法运…

数据安全:Web3时代的隐私保护新标准

随着数字化时代的到来&#xff0c;我们的生活已经完全依赖于互联网和数据交换。然而&#xff0c;随之而来的是对个人隐私和数据安全的日益关注。在这个信息爆炸的时代&#xff0c;数据泄露、个人隐私侵犯和网络攻击等问题日益突出&#xff0c;而Web3技术的崛起正带来了一种全新…

django上课点名系统-计算机毕业设计源码03391

摘 要 随着现在网络的快速发展&#xff0c;网络的应用在各行各业当中它很快融入到了许多学校的眼球之中&#xff0c;他们利用网络来做这个签到点名的网站&#xff0c;随之就产生了“上课点名系统 ”&#xff0c;这样就让学生上课点名系统更加方便简单。 对于本上课点名系统的设…

面试题(常见)

1.项目使用的框架&#xff0c;数据库 2.mysql索引有哪些&#xff0c;有什么区别 3.mysql 引擎有哪些 4.了解那些框架&#xff0c;有什么区别 5.springboot 常用的注解有哪些&#xff0c;什么作用&#xff0c;作用原理是什么 6.inner join &#xff0c;left join 查询数据结…

介绍spark中的模型选择与验证技术

模型选择与验证技术 在机器学习中&#xff0c;模型选择和验证技术是确保模型性能和避免过拟合的重要步骤。下面介绍一些常用的方法和工具。 1. 参数网格构建器 (ParamGridBuilder) 用途&#xff1a;用于构建参数网格&#xff0c;以便在网格搜索中选择最佳模型参数。 原理&a…

CS5518芯片设计|替代GM8775设计方案|MIPI转LVDS芯片方案|DSI转LVDS芯片方案

CS5518支持常见的1920*1080分辨率的屏&#xff0c;支持视频格式为 FULL HD&#xff08;1920 x 1200&#xff09;。为MIPI DSI 转LVDS 双通道桥接芯片&#xff0c;实现将MIPI DSI信号转换为单/双通道 LVDS输出功能&#xff0c;MIPI 支持1/2/3/4 通道可选,支持 4Gbps 速率。LVDS …

力扣1049 最后一块石头的重量Ⅱ Java版本

文章目录 题目描述思路代码 题目描述 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的…

Adaboost集成学习 | Matlab实现基于CNN-LSTM-Adaboost集成学习时间序列预测(股票价格预测)

目录 效果一览基本介绍模型设计程序设计参考资料 效果一览 基本介绍 Adaboost集成学习 | Matlab实现基于CNN-LSTM-Adaboost集成学习时间序列预测&#xff08;股票价格预测&#xff09; 模型设计 融合Adaboost的CNN-LSTM模型的时间序列预测&#xff0c;下面是一个基本的框架。 …

编程软件怎么给机器人编程:深入探索编程与机器人技术的融合

编程软件怎么给机器人编程&#xff1a;深入探索编程与机器人技术的融合 随着科技的飞速发展&#xff0c;机器人技术已经深入到我们生活的方方面面。而要让机器人按照我们的意愿执行任务&#xff0c;就需要借助编程软件对机器人进行编程。那么&#xff0c;编程软件究竟是如何给…

在vue和uniapp中使用 websocket并封装js

vue中 websocket.js import store from /store import { Message } from element-ui var ws; var tt; var lockReconnect false;//避免重复连接 var clientId localStorage.getItem("clientId")//缓存中取出客户端idvar websocket {Init: function (url, clien…

HTML 区块

HTML 区块 HTML&#xff08;超文本标记语言&#xff09;是构建网页的标准语言&#xff0c;它定义了网页的结构和内容。在HTML中&#xff0c;区块元素是用来组织页面内容的重要工具。这些元素通常用于创建如段落、列表、头部、底部、导航栏等较大的内容块。本文将详细介绍HTML中…

JavaScript 错误解析与最佳实践:隐式返回对象字面量的正确写法

在JavaScript开发中&#xff0c;箭头函数&#xff08;Arrow Functions&#xff09;因其简洁的语法和灵活的功能而广受欢迎。然而&#xff0c;在使用箭头函数返回对象字面量时&#xff0c;开发者常常会遇到一些语法错误。本文将通过一个常见的错误示例&#xff0c;详细解析其原因…

网络安全攻防演练:提升应急响应能力

网络安全攻防演练&#xff1a;提升应急响应能力 在网络攻击日益频繁和复杂的今天&#xff0c;网络安全攻防演练成为提升组织应急响应能力的重要手段。通过模拟真实攻击场景&#xff0c;攻防演练能够帮助组织检验和提高其网络安全防护和应急处理能力。 一、网络安全攻防演练的…

探索微软Edge:新时代的浏览器先锋

随着互联网的快速发展&#xff0c;浏览器在我们日常生活中扮演着越来越重要的角色。微软Edge作为一款现代化的浏览器&#xff0c;以其独特的功能和优越的性能吸引了大量用户。本文将深入探索微软Edge&#xff0c;揭示其亮点和优势&#xff0c;帮助你更好地了解和使用这款浏览器…

【Tomcat】日志相关设置

Tomcat的日志文件设置涉及到多个方面&#xff0c;包括日志文件的存放位置、日志类型、日志级别以及日志的滚动和分割等。以下是一个清晰的Tomcat日志文件设置指南&#xff0c;参考了上述文章中的信息&#xff1a; 1. 日志文件存放位置 Tomcat的日志文件通常存放在Tomcat安装目…

前端必看的2024 年 7 个 Web 前端开发趋势【文末福利=网盘分享2024web前端技术资料,学习资源】

目录 前言 趋势一&#xff1a;新的样式解决方案和组件库将持续涌现 趋势二&#xff1a;利用 AI 来增强开发流程 趋势三&#xff1a;SSR 和 SSG 两种框架之间的竞争将会愈演愈烈 趋势四&#xff1a;前端、后端和全栈开发之间的界限将越来越模糊 趋势五&#xff1a;越来越多的人…

Python数据库编程指南:连接与操作SQLite与MySQL

目录 一、引言 二、SQLite数据库连接与操作 &#xff08;一&#xff09;安装SQLite库 &#xff08;二&#xff09;建立数据库连接 &#xff08;三&#xff09;执行SQL语句 &#xff08;四&#xff09;注意事项 三、MySQL数据库连接与操作 &#xff08;一&#xff09;安…

阿里云 Ubuntu 22.04.4 LTS 安装postfix+dovecot 搭建邮件服务器

一 安装 1安装postfix sudo apt-get install postfix #如果没有弹出配置界面&#xff0c;运行 dpkg-reconfigure postfix #sudo vim /etc/postfix/main.cf smtpd_banner $myhostname ESMTP $mail_name (Ubuntu) biff no append_dot_mydomain no readme_directory no co…

Leetcode.2786 访问数组中的位置使分数最大

题目链接 Leetcode.2786 访问数组中的位置使分数最大 rating : 1732 题目描述 给你一个下标从 0 0 0 开始的整数数组 n u m s nums nums 和一个正整数 x x x 。 你 一开始 在数组的位置 0 0 0 处&#xff0c;你可以按照下述规则访问数组中的其他位置&#xff1a; 如果你…

阿里云 OpenSearch RAG 应用实践

2024年5月18日&#xff0c;阿里巴巴 OpenSearch 研发负责人刑少敏应邀参与AICon全球人工智能开发与应用大会暨大模型应用生态展&#xff0c;分享《OpenSearch RAG 应用实践》&#xff0c;介绍了阿里云OpenSearch在RAG方面的应用和探索。以下是主题演讲的逐字稿分享&#xff1a;…