LeetCode236. 二叉树的最近公共祖先(后序遍历 DFS)

本文详细解析了二叉树的最近公共祖先问题,包括LeetCode 236题目的描述与解决方案。通过递归后序遍历的方法,当遇到节点p或q时返回,从底至顶回溯,当节点p,q在节点root的异侧时,节点root即为最近公共祖先。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、题目描述

236. 二叉树的最近公共祖先 - 力扣(LeetCode)

相关题:68-1二叉搜索树的最近公共祖先(剑)LeetCode.235 68-1:二叉搜索树的最近公共祖先(剑指offer第2版Python)LeetCode.235_leetcode 剑指 offer 68 - ii python-CSDN博客

2、代码详解

# Definition for a binary tree node.
class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        # 若当前节点为空,或者当前节点就是 p 或 q 节点,直接返回当前节点
        if not root or root == p or root == q:
            return root

        # 递归遍历左子树,查找 p 和 q 的最近公共祖先
        left = self.lowestCommonAncestor(root.left, p, q)
        # 递归遍历右子树,查找 p 和 q 的最近公共祖先
        right = self.lowestCommonAncestor(root.right, p, q)

        # 情况 1:左子树和右子树都没有找到 p 和 q,说明 p 和 q 不在当前节点的子树中,返回 None
        if not left and not right:
            return None

        # 情况 2:左子树没有找到 p 和 q,说明 p 和 q 都在右子树中,返回右子树的查找结果
        if not left:
            return right

        # 情况 3:右子树没有找到 p 和 q,说明 p 和 q 都在左子树中,返回左子树的查找结果
        if not right:
            return left

        # 情况 4:左子树和右子树都找到了 p 或 q,说明 p 和 q 分别在当前节点的左右子树中,当前节点就是最近公共祖先,返回当前节点
        return root

def main():
    # 构建一个简单的二叉树
    #       3
    #      / \
    #     5   1
    #    /|   |\
    #   6 2   0 8
    #     |\
    #    7 4
    root = TreeNode(3)
    root.left = TreeNode(5)
    root.right = TreeNode(1)
    root.left.left = TreeNode(6)
    root.left.right = TreeNode(2)
    root.right.left = TreeNode(0)
    root.right.right = TreeNode(8)
    root.left.right.left = TreeNode(7)
    root.left.right.right = TreeNode(4)

    # 假设要查找 5 和 1 的最近公共祖先
    p = root.left  # 节点 5
    q = root.right  # 节点 1

    solution = Solution()
    # 调用 lowestCommonAncestor 方法查找最近公共祖先
    result = solution.lowestCommonAncestor(root, p, q)
    if result:
        print(f"节点 {p.val} 和节点 {q.val} 的最近公共祖先是节点 {result.val}")
    else:
        print("未找到最近公共祖先")

if __name__ == "__main__":
    main()

复杂度分析:
时间O(N) : 其中 N 为二叉树节点数;最差情况下,需要递归遍历树的所有节点。
空间O(H) :其中 H是二叉树的高度。递归调用栈的深度最大为二叉树的高度。在最坏情况下,二叉树退化为链表,空间复杂度为 O(N) 。

https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/solutions/240096/236-er-cha-shu-de-zui-jin-gong-gong-zu-xian-hou-xu/

# Definition for a binary tree node.
class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def lowestCommonAncestor(self, root, p, q):
        """
        :type root: TreeNode
        :type p: TreeNode
        :type q: TreeNode
        :rtype: TreeNode
        """
        if not root or root == p or root == q:
            return root
        
        # 通过递归对二叉树进行 后序遍历,当遇到节点 p 或 q 时返回。
        # 从底至顶回溯,当节点 p, q 在节点 root 的异侧时,节点 root 即为最近公共祖先,则向上返回 root 。
        
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        if not left and not right:
            return  # 1.说明 root 的左 / 右子树中都不包含 p,q,返回 null
        if not left:
            # 3.p,q 都不在 root 的左子树中,直接返回 right,具体可分为两种情况:
            # p,q 其中一个在 root 的 右子树 中,此时 right 指向 p(假设为 p )
            # p,q 两节点都在 root 的 右子树 中,此时的 right 指向 最近公共祖先节点
            return right
        if not right:
            return left  # 4.同理3
        return root  # 2. if left and right: 同时不为空 :说明 p, q 分列在 root 的 异侧 (分别在 左 / 右子树),因此 root 为最近公共祖先,返回 root

236. 二叉树的最近公共祖先 - 力扣(LeetCode)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值