LeetCode 题集:深度优先搜索(DFS)、广度优先搜索(BFS)

本文介绍 LeetCode 题集中,有关深度优先搜索(DFS)和广度优先搜索(BFS)的问题。


110. Balanced Binary Tree(平衡二叉树)


问题描述

LeetCode 110 问题描述 I
LeetCode 110 问题描述 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 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)

运行效果:
LeetCode 110 运行效果 1

效果有些不理想,这里提出一种优化方案。由于只要有一个子节点下为不平衡树,整体即为不平衡树,因此可以在获取深度时即做剪枝。

代码如下:

# 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)

运行效果:
LeetCode 110 运行效果 2


111. Minimum Depth of Binary Tree(二叉树的最小深度)


问题描述


LeetCode 111 问题描述 I
LeetCode 111 问题描述 II

思路与代码


关于本题,介绍深度优先搜索和广度优先搜索两种思路。

深度优先搜索(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)

运行结果:
LeetCode 111 运行效果

广度优先搜索(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

运行效果:
LeetCode 111 运行效果 2


112. Path Sum(路径总和)


问题描述

LeetCode 112 问题描述 I
LeetCode 112 问题描述 II

思路与代码


在本题中,由于只需有一条路径满足要求,即可返回 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)

运行效果:
LeetCode 112 运行效果


113. Path Sum II(路径总和 II)


问题描述

LeetCode 113 问题描述 I
LeetCode 113 问题描述 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

运行效果:
LeetCode 113 运行效果


102. Binary Tree Level Order Traversal(二叉树的层序遍历)


问题描述

LeetCode 102问题描述 I
LeetCode 102问题描述 II

思路与代码


在本题中,由于返回结果是每层节点值处于同一列表的,因此自然想到广度优先搜索的方式。此外,通过深度优先搜索的方式求解本题也比较方便。

广度优先搜索(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

运行效果:
LeetCode 102 运行效果 1

深度优先搜索(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

运行结果:
LeetCode 102 运行效果 2

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值