本文介绍 LeetCode 题集中,有关深度优先搜索(DFS)和广度优先搜索(BFS)的问题。
110. Balanced Binary Tree(平衡二叉树)
问题描述
思路与代码
本题可采用深度优先搜索的方法,遍历每一个子节点下是否为平衡树,输出最终结果。
代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
def run(root: TreeNode) -> bool:
def get_depth(root: TreeNode):
if not root:
return 0
else:
return max(get_depth(root.left), get_depth(root.right)) + 1
if not root:
return True
# not balanced
if abs(get_depth(root.left) - get_depth(root.right)) > 1:
return False
return run(root.left) and run(root.right)
return run(root=root)
运行效果:
效果有些不理想,这里提出一种优化方案。由于只要有一个子节点下为不平衡树,整体即为不平衡树,因此可以在获取深度时即做剪枝。
代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
def run(root: TreeNode) -> bool: # 返回 -1 即为提前剪枝
def get_depth(root: TreeNode):
if not root:
return 0
lh = get_depth(root.left)
if lh == -1:
return -1
rh = get_depth(root.right)
if rh == -1:
return -1
if abs(lh - rh) > 1:
return -1
return max(lh, rh) + 1
if not root:
return True
return get_depth(root) != -1
return run(root=root)
运行效果:
111. Minimum Depth of Binary Tree(二叉树的最小深度)
问题描述
思路与代码
关于本题,介绍深度优先搜索和广度优先搜索两种思路。
深度优先搜索(DFS)
深度优先搜索采用递归的方式实现。
代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDepth(self, root: TreeNode) -> int:
def run(root: TreeNode) -> int:
if not root:
return 0
ld = run(root.left)
rd = run(root.right)
if not ld:
return rd + 1
elif not rd:
return ld + 1
return min(ld, rd) + 1
return run(root=root)
运行结果:
广度优先搜索(BFS)
广度优先搜索采用队列的数据结构实现,此处采用 Python 语言的 list 数据类型模拟队列的操作。
由于本题是要返回最小深度,即一定要遍历完最小深度所在节点的上一层的全部节点,但不必遍历全部叶子节点,因此广度优先搜索会更高效。
代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minDepth(self, root: TreeNode) -> int:
if not root:
return 0
list_queue = []
list_queue.append(root)
min_depth = 1
while list_queue:
cur_size = len(list_queue)
for i in range(cur_size):
# pop the head of queue
node = list_queue[0]
list_queue = list_queue[1:]
# no child nodes
if not node.left and not node.right:
return min_depth
# add child nodes to queue
if node.left:
list_queue.append(node.left)
if node.right:
list_queue.append(node.right)
min_depth += 1
return min_depth
运行效果:
112. Path Sum(路径总和)
问题描述
思路与代码
在本题中,由于只需有一条路径满足要求,即可返回 true,因此深度优先搜索的方法更合适。此外,本题需要注意两种情况:
- 节点的数值可正可负,因此只有搜索到每个叶子节点才能判断一条路径是否符合要求
- 如果输入为空树,无论目标值是否为 0,搜要返回 false
代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
def backtrack(node: TreeNode, target: int) -> bool:
target -= node.val
if not target:
if not node.left and not node.right:
return True
if node.left:
if backtrack(node=node.left, target=target):
return True
if node.right:
if backtrack(node=node.right, target=target):
return True
return False
return backtrack(node=root, target=targetSum)
运行效果:
113. Path Sum II(路径总和 II)
问题描述
思路与代码
本题为前一题的变体,由于需要返回所有可行路径,因此采用回溯法求解。此处依旧采用深度优先搜索的方法。
代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
if not root:
return []
list_solution = []
solution = []
def backtrack(node: TreeNode, target: int):
target -= node.val
solution.append(node.val)
if not target:
if not node.left and not node.right:
list_solution.append(solution.copy())
solution.pop()
return
if node.left:
backtrack(node=node.left, target=target)
if node.right:
backtrack(node=node.right, target=target)
solution.pop()
backtrack(node=root, target=targetSum)
return list_solution
运行效果:
102. Binary Tree Level Order Traversal(二叉树的层序遍历)
问题描述
思路与代码
在本题中,由于返回结果是每层节点值处于同一列表的,因此自然想到广度优先搜索的方式。此外,通过深度优先搜索的方式求解本题也比较方便。
广度优先搜索(BFS)
代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
list_result = []
list_node_last = [root]
list_result.append([root.val])
while list_node_last:
list_node, list_value = [], []
for node in list_node_last:
if node.left:
list_node.append(node.left)
list_value.append(node.left.val)
if node.right:
list_node.append(node.right)
list_value.append(node.right.val)
list_node_last = list_node
if list_value:
list_result.append(list_value)
return list_result
运行效果:
深度优先搜索(DFS)
代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
list_result = []
def dfs(node: TreeNode, depth: int):
if depth <= len(list_result):
list_result[depth - 1].append(node.val)
else:
list_result.append([node.val])
if node.left:
dfs(node=node.left, depth=depth + 1)
if node.right:
dfs(node=node.right, depth=depth + 1)
dfs(node=root, depth=1)
return list_result
运行结果: