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

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦
欢迎关注、订阅专栏 【力扣详解】谢谢你的支持!
⭐ 题目描述:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
- 最近公共祖先:对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)
- 图示节点 4 和 节点 6 的最近公共祖先为节点 5:

🔥 思路:需要结合左、右孩子的情况确定当前节点的身份,所以采用 后续遍历;判定当前节点的身份为最近公共祖先分 两种情况
- 情况一:如果当前节点为一个指定节点且其左 or 右子树中包含另一指定节点
- 情况二:如果当前节点的左、右子树分别包含两个指定节点
⭐题目准备之后续遍历:一定要先掌握后续遍历 ❗❗❗ 放在最后面啦,供不熟悉的友友参考~
参考如上思路,给出详细步骤如下:如果遍历遇到
q
,就将q
返回,遇到p
就将p
返回,那么如果左右⼦树的返回值都不为空(情况二),说明此时的中节点,⼀定是q
和p
的最近公共祖先;⚡ 情况一不需要额外处理,已包含 (参见步骤二)
- 步骤一⭐确定递归函数
traversal
参数及返回值
- 参数:需要根据当前节点
current
和 指定节点p
q
来判断当前节点current
的情况- 返回值:返回当前节点
current
对应子树下是否有 p 或 q- 步骤二⭐确定递归终止条件: 找到
p
或 找到q
或 走到了None
节点
- 当前节点
current
为p
或q
后不需要进一步遍历该子树寻找另一指定节点, 因为若该子树内有另一指定节点(⚡情况一) -> 说明当前节点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