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

2024-06-15 15:28

本文主要是介绍LeetCode题练习与总结:单词接龙--127,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、题目描述

字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk

  • 每一对相邻的单词只差一个字母。
  •  对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord 不需要在 wordList 中。
  • sk == endWord

给你两个单词 beginWord 和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0 。

 

示例 1:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出:5
解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。

示例 2:

输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出:0
解释:endWord "cog" 不在字典中,所以无法进行转换。

提示:

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

二、解题思路

  1. 将单词列表转换为图:首先,我们需要构建一个图,其中包含 wordList 中的所有单词。这可以通过比较每对单词并检查它们是否只有一个字符不同来实现。

  2. 广度优先搜索:从 beginWord 开始,进行广度优先搜索,寻找 endWord。在搜索过程中,我们记录从 beginWord 到当前单词的路径长度。

  3. 终止条件:一旦我们找到了 endWord,我们就知道我们已经找到了最短的转换序列,并且可以返回当前的路径长度。

  4. 优化:为了提高搜索效率,我们可以在开始 BFS 之前预处理 wordList,创建一个通用状态映射,这样我们可以快速找到所有与给定单词只有一个字符差异的单词。

三、具体代码

import java.util.*;public class Solution {public int ladderLength(String beginWord, String endWord, List<String> wordList) {// 将单词列表转换为集合,便于快速查找Set<String> wordSet = new HashSet<>(wordList);if (!wordSet.contains(endWord)) return 0;// BFS 队列Queue<String> queue = new LinkedList<>();queue.offer(beginWord);// 记录已访问的单词Set<String> visited = new HashSet<>();visited.add(beginWord);// 记录转换序列的长度int level = 1;while (!queue.isEmpty()) {int size = queue.size();for (int i = 0; i < size; i++) {String currentWord = queue.poll();// 如果找到了结束单词if (currentWord.equals(endWord)) {return level;}// 遍历当前单词的所有可能转换for (String nextWord : getNextWords(currentWord, wordSet)) {if (!visited.contains(nextWord)) {queue.offer(nextWord);visited.add(nextWord);}}}level++;}return 0;}// 获取当前单词的所有可能转换private List<String> getNextWords(String word, Set<String> wordSet) {List<String> nextWords = new ArrayList<>();for (char ch = 'a'; ch <= 'z'; ch++) {for (int i = 0; i < word.length(); i++) {// 生成下一个可能的单词String nextWord = replace(word, i, ch);if (wordSet.contains(nextWord)) {nextWords.add(nextWord);}}}return nextWords;}// 替换单词中的某个字符private String replace(String word, int index, char ch) {char[] chars = word.toCharArray();chars[index] = ch;return new String(chars);}
}

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

1. 时间复杂度
  • 构建 wordSet:将 wordList 转换为 HashSet 的时间复杂度是 O(N),其中 N 是 wordList 的长度。

  • BFS 遍历:在 BFS 过程中,每个单词都可能生成 26 * L 个新单词,其中 L 是单词的长度。在最坏的情况下,所有单词都可能被访问一次。因此,时间复杂度是 O(N * 26 * L)。

  • getNextWords 函数:对于每个单词,我们检查 26 * L 个可能的转换。这个操作的时间复杂度是 O(26 * L)。

  • replace 函数:这个函数的时间复杂度是 O(L),因为我们只是替换了一个字符并生成了一个新的字符串。

  • 综上所述,总的时间复杂度是 O(N * 26 * L)。

2. 空间复杂度
  • wordSet 和 visited:这两个 HashSet 最多存储 N 个单词,因此它们的空间复杂度是 O(N)。

  • 队列 queue:在 BFS 过程中,队列中最多可能存储 N 个单词,因此空间复杂度是 O(N)。

  • nextWords 列表:在 getNextWords 函数中,这个列表最多可能存储 26 * L 个单词,因此空间复杂度是 O(26 * L)。

  • 其他变量:如 level 和循环中的临时变量等,它们的空间复杂度是 O(1)。

  • 综上所述,总的空间复杂度是 O(N + 26 * L)。

综合来看,这个算法的时间复杂度是 O(N * 26 * L),空间复杂度是 O(N + 26 * L)。

五、总结知识点

  1. 集合的使用HashSet 用于存储不重复的元素,并提供了快速的查找、添加和删除操作。代码中使用了 HashSet 来存储 wordList 和已访问的单词。

  2. 队列的使用LinkedList 作为队列使用,实现了先进先出的数据结构。在 BFS 过程中,队列用于存储待访问的单词。

  3. 广度优先搜索(BFS):这是一种图遍历算法,用于在图中找到最短路径。代码中使用了 BFS 来找到从 beginWord 到 endWord 的最短转换序列。

  4. 字符串操作replace 函数展示了如何通过索引替换字符串中的字符。这涉及到字符串转字符数组,然后修改数组中的元素,最后将数组转回字符串。

  5. 循环和条件语句:代码中使用了 for 循环来遍历单词的每个字符和字母表中的每个字符,以及 if 语句来检查条件。

  6. 函数定义和调用:代码中定义了 ladderLengthgetNextWords 和 replace 三个函数,分别用于解决不同的问题。函数的定义和调用展示了模块化编程的思想。

  7. 字符和字符数组:代码中使用了字符变量 ch 来遍历字母表,并使用了字符数组 chars 来表示和操作字符串。

  8. 数据结构的选择:代码中选择合适的数据结构(如 HashSet 和 Queue)来优化算法的性能,特别是在单词查找和图遍历方面。

  9. 算法设计:代码实现了基于 BFS 的图遍历算法,这是一种常见的算法设计技巧,用于解决最短路径问题。

  10. 递归和迭代:虽然代码中没有直接使用递归,但 BFS 本身是一种递归思想的迭代实现,每次迭代都相当于展开递归的一层。

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

这篇关于LeetCode题练习与总结:单词接龙--127的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1063843

相关文章

Python中连接不同数据库的方法总结

《Python中连接不同数据库的方法总结》在数据驱动的现代应用开发中,Python凭借其丰富的库和强大的生态系统,成为连接各种数据库的理想编程语言,下面我们就来看看如何使用Python实现连接常用的几... 目录一、连接mysql数据库二、连接PostgreSQL数据库三、连接SQLite数据库四、连接Mo

Git提交代码详细流程及问题总结

《Git提交代码详细流程及问题总结》:本文主要介绍Git的三大分区,分别是工作区、暂存区和版本库,并详细描述了提交、推送、拉取代码和合并分支的流程,文中通过代码介绍的非常详解,需要的朋友可以参考下... 目录1.git 三大分区2.Git提交、推送、拉取代码、合并分支详细流程3.问题总结4.git push

Kubernetes常用命令大全近期总结

《Kubernetes常用命令大全近期总结》Kubernetes是用于大规模部署和管理这些容器的开源软件-在希腊语中,这个词还有“舵手”或“飞行员”的意思,使用Kubernetes(有时被称为“... 目录前言Kubernetes 的工作原理为什么要使用 Kubernetes?Kubernetes常用命令总

Python中实现进度条的多种方法总结

《Python中实现进度条的多种方法总结》在Python编程中,进度条是一个非常有用的功能,它能让用户直观地了解任务的进度,提升用户体验,本文将介绍几种在Python中实现进度条的常用方法,并通过代码... 目录一、简单的打印方式二、使用tqdm库三、使用alive-progress库四、使用progres

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Java向kettle8.0传递参数的方式总结

《Java向kettle8.0传递参数的方式总结》介绍了如何在Kettle中传递参数到转换和作业中,包括设置全局properties、使用TransMeta和JobMeta的parameterValu... 目录1.传递参数到转换中2.传递参数到作业中总结1.传递参数到转换中1.1. 通过设置Trans的

C# Task Cancellation使用总结

《C#TaskCancellation使用总结》本文主要介绍了在使用CancellationTokenSource取消任务时的行为,以及如何使用Task的ContinueWith方法来处理任务的延... 目录C# Task Cancellation总结1、调用cancellationTokenSource.

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;