开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情
作者: 千石
支持:点赞、收藏、评论
欢迎各位在评论区交流
前言
本文内容来自我平时学习的一些积累,如有错误,还请指正
在题目实战部分,我将代码实现和代码解释设置在了解题思路的下方,方便各位作为参考刷题
一些话
本文内容来自我平时学习的一些积累,如有错误,还请指正
在题目实战部分,我将代码实现和代码解释设置在了解题思路的下方,方便各位作为参考刷题
题目练习步骤:
- 给自己10分钟,读题并思考解题思路
- 有了思路以后开始写代码,如果在上一步骤中没有思路则停止思考并且看该题题解
- 在看懂题解(暂时没看懂也没关系)的思路后,背诵默写题解,直至能熟练写出来
- 隔一段时间,再次尝试写这道题目
前置知识
这一部分可以看看我写的这篇题解,题解中介绍了这两种算法:【后端部分】青训营题目的思维拓展:解题思路分享 - 掘金 (juejin.cn)
实战
题目一:102. 二叉树的层序遍历
解题思路
使用 BFS 的思路如下:
-
使用队列,将根节点入队。
-
只要队列不为空,循环以下操作:
- 将队头节点出队,并将该节点的值存入结果数组。
- 如果左子节点不为空,将其入队。
- 如果右子节点不为空,将其入队。
-
返回结果数组。
代码如下:
from collections import deque
class Solution:
def levelOrder(self, root: TreeNode):
if not root:
return []
result = []
queue = deque([root])
while queue:
level = []
for i in range(len(queue)):
node = queue.popleft()
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(level)
return result
时间复杂度:O(n),因为每个节点最多被遍历一次。
使用 DFS 的思路如下:
- 使用递归,分别处理当前层的每个节点。
- 对于当前节点,先将其值存入当前层的结果数组。
- 如果左子节点不为空,递归处理。
- 如果右子节点不为空,递归处理。
- 返回结果数组。
代码如下:
from collections import deque
class Solution:
def levelOrder(self, root: TreeNode):
def dfs(node, level):
if not node:
return
if len(result) < level + 1:
result.append([])
result[level].append(node.val)
dfs(node.left, level + 1)
dfs(node.right, level + 1)
result = []
dfs(root, 0)
return result
时间复杂度:O(n),因为每个节点最多被遍历一次。
题目二:433. 最小基因变化
使用 BFS 的思路如下:
使用队列进行广度优先搜索,对于每一层的每一个字符串进行改变,生成新的字符串,如果新的字符串存在于基因库中,就将其加入队列。如果新的字符串等于 end,则返回当前层数。
from collections import deque
class Solution:
def minMutation(self, start: str, end: str, bank: List[str]) -> int:
def can_transform(a, b):
count = 0
for i in range(8):
if a[i] != b[i]:
count += 1
if count > 1:
return False
return count == 1
queue = deque([start])
level = 0
bank = set(bank)
while queue:
size = len(queue)
level += 1
for i in range(size):
curr = queue.popleft()
for j in bank:
if can_transform(curr, j):
if j == end:
return level
queue.append(j)
bank.remove(j)
return -1
时间复杂度:O(N * L ^ 2),其中N为基因库中的字符串数量,L为字符串长度。
使用 DFS 的思路如下:
对于每一个可能的变换方案,我们都从当前的start状态向下搜索,看看是否能够到达最终的end状态。 如果可以,就返回当前的变换步数。如果不可以,就返回-1。
代码实现:
class Solution:
def minMutation(self, start: str, end: str, bank: List[str]) -> int:
def dfs(start, end, bank, path, visited):
if start == end:
return len(path)
for i in range(len(bank)):
if bank[i] not in visited and sum([start[j] != bank[i][j] for j in range(len(start))]) == 1:
visited.add(bank[i])
res = dfs(bank[i], end, bank, path + [bank[i]], visited)
if res != -1:
return res
visited.remove(bank[i])
return -1
return dfs(start, end, bank, [start], set([start]))
时间复杂度:O(N * L), 其中N是bank数组的大小,L是序列长度。