LeetCode 栈、队列、优先队列专题 5:广度优先遍历和图的最短路径问题

在图中进行广度优先遍历(BFS),进而寻找最短的路径。

例:LeetCode 第 279 题:完全平方式

传送门:279. 完全平方数。

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

示例 1:

输入: n = 12
输出: 3 
解释: 12 = 4 + 4 + 4.

示例 2:

输入: n = 13
输出: 2
解释: 13 = 4 + 9.

Python 代码:


练习:LeetCode 第 127 题:单词接龙

传送门:127. 单词接龙。

给定两个单词(beginWordendWord)和一个字典,找到从 beginWordendWord 的最短转换序列的长度。转换需遵循如下规则:

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

说明:

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

示例 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" 不在字典中,所以无法进行转换。

分析:这道题目可以建模成一个有向图,原问题就可以抽象成一个有向无权图的最短路径问题,可以称之为套路的解决方案就是“广度优先遍历(BFS)”,明白了这些以后,写出正确的代码就不是难事。

注意:(1)“图”的广度优先遍历使用的辅助数据结构有两个,一个是队列(用于一层一层排队),一个是一个数组或者是集合(用于判断当前考虑的元素是否以前已经处理过)。

回顾:如果是树结构的广度优先遍历,就无需设置辅助的数组或者集合用于判断以前是否处理过。

其实,只要思路很清楚,写出 AC 解就是自然而然的事情了。这里我说的自然而然是相比较于要考虑很多特殊情况(边界情况,+1或者 -1 情况)的简单问题来说,这道问题应该划分到简单。毕竟广度优先遍历是一个常规问题,不需要使用到什么小技巧。

下面谈一谈我在解题过程中的一些优化:

(1)原来是遍历 wordList,看看目标 word 与它们只差一个字母的情况,此时在 wordList 很大的情况下效率低下,故将 wordList 改成 HashSet,利用 HashSet 查询高效性避免了去遍历这件事情;

(2)char[] 数组这件事情,其实还可以用 StringBuilder。(3)考虑能不能使用 Trie。

Python 代码:

练习:LeetCode 第 126 题:单词接龙 II

传送门:126. 单词接龙 II。

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

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

说明:

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

示例 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" 不在字典中,所以不存在符合要求的转换序列。

分析:很遗憾,我自己只写出了超时解。不过思路至少还是对的。先使用广度优先搜索得到最短层数,再使用深度优先搜索得到所有的最短路径。

Python 代码:

(本节完)

你可能感兴趣的:(LeetCode 栈、队列、优先队列专题 5:广度优先遍历和图的最短路径问题)