LeetCode 热题 HOT 100 (002/100)【宇宙最简单版】

【二叉树】No. 0236 二叉树的最近公共祖先 【中等】👉力扣对应题目指路

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦
欢迎关注、订阅专栏 【力扣详解】谢谢你的支持!

题目描述:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

  • 最近公共祖先:对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)
  • 图示节点 4 和 节点 6 的最近公共祖先为节点 5:

🔥 思路:需要结合左、右孩子的情况确定当前节点的身份,所以采用 后续遍历;判定当前节点的身份为最近公共祖先分 两种情况

  • 情况一:如果当前节点为一个指定节点且其左 or 右子树中包含另一指定节点
  • 情况二:如果当前节点的左、右子树分别包含两个指定节点

⭐题目准备之后续遍历:一定要先掌握后续遍历 ❗❗❗ 放在最后面啦,供不熟悉的友友参考~


参考如上思路,给出详细步骤如下:如果遍历遇到 q,就将 q 返回,遇到 p 就将 p 返回,那么如果左右⼦树的返回值都不为空(情况二),说明此时的中节点,⼀定是 qp 的最近公共祖先;⚡ 情况一不需要额外处理,已包含 (参见步骤二)

  • 步骤一⭐确定递归函数 traversal 参数及返回值
    • 参数:需要根据当前节点 current 和 指定节点 p q 来判断当前节点 current 的情况
    • 返回值:返回当前节点 current 对应子树下是否有 p 或 q
  • 步骤二⭐确定递归终止条件: 找到 p 或 找到 q 或 走到了 None 节点
    • 当前节点 currentpq 后不需要进一步遍历该子树寻找另一指定节点, 因为若该子树内有另一指定节点(⚡情况一) -> 说明当前节点 current 就为最近公共祖先,仍是采用 return current
  • 步骤三⭐确定单层递归逻辑-后序处理:根据左、右子树的递归返回值情况,确定当前节点的返回值
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        def traversal(current):  #---------------------------------------- step1 
            if current == None or current == p or current == q:  # ------- step2
                return current
           
            # ------------------------------------------------------------ step3
            ## 左
            result_left = traversal(current.left)
            ## 右
            result_right = traversal(current.right)
            ## 中
            if result_left and result_right:  
                return current
            if result_left: return result_left      ## 注意不是返回 current.left
            if result_right: return result_right    ## 注意不是返回 current.right
            return None

        return traversal(root)

⭐⭐⭐ 题目准备之后续遍历:一定要先掌握后续遍历 ❗❗❗

# 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
        """
        self.result = []

        def traversal(current):
            if current == None:
                return
            print('-------------------------Hi, node: ', current.val)
            traversal(current.left)
            traversal(current.right)
            print('----- current_val: ', current.val)  // 观察此处的处理顺序,是后序
            self.result.append(current.val)
        
        traversal(root)  ## self.result: [6, 7, 4, 2, 5, 0, 8, 1, 3]
  • 对应的输出结果如下:
    ('-------------------------Hi, node: ', 3)
    ('-------------------------Hi, node: ', 5)
    ('-------------------------Hi, node: ', 6)
    ('----- current_val: ', 6)
    ('-------------------------Hi, node: ', 2)
    ('-------------------------Hi, node: ', 7)
    ('----- current_val: ', 7)
    ('-------------------------Hi, node: ', 4)
    ('----- current_val: ', 4)
    ('----- current_val: ', 2)
    ('----- current_val: ', 5)
    ('-------------------------Hi, node: ', 1)
    ('-------------------------Hi, node: ', 0)
    ('----- current_val: ', 0)
    ('-------------------------Hi, node: ', 8)
    ('----- current_val: ', 8)
    ('----- current_val: ', 1)
    ('----- current_val: ', 3)
    
    

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦
🔥 LeetCode 热题 HOT 100

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值