1. 题目
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
2. 解题思路
详情见 面试题68 - II. 二叉树的最近公共祖先(后序遍历 DFS ,清晰图解)
关键点是二叉搜索树,研究发现有如下规律。
三种情况:1)p, q 一个在左子树,一个在右子树,那么当前节点就是最近公共祖先 2)p, q 都在左子树 3) p, q 都在右子树
3. 代码实现
3.0 路径比较
这个是我自己想到的,看了leetcode的题解之后,感觉自己就是个渣渣。o(╥﹏╥)o
# 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:
"""
1. 记录找到p和q的路径
2. 从找到p和q的第一个公共祖先
"""
def helper(cur, p):
"""
返回p在cur树中的路径,路径肯定是唯一的
"""
path = [None] # 路径
stack = [(None, cur)]
while cur:
father, cur = stack.pop()
while path[-1] != father: path.pop()
path.append(cur)
if p.val == cur.val: break # 找到p了
if cur.right: stack.append((cur, cur.right))
if cur.left: stack.append((cur, cur.left))
if not (cur.right or cur.left): path.pop()
return path[:0:-1]
ps = helper(root, p)
qs = helper(root, q)
for i in ps: # 找到最近公共祖先
for j in qs:
if i == j:
return j
return
3.1 递归
# 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:
if not root or root == p or root == q: return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if not left: return right
if not right: return left
return root
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
"""
思路:
三种情况:
1)p, q 一个在左子树,一个在右子树,那么当前节点就是最近公共祖先
2)p, q 都在左子树
3) p, q 都在右子树
所以,若返回值中l和r都是节点,表明左右子树中一边一个节点
若返回值中l和r只有一个是节点,表明两个节点都在某一侧的子树中
"""
if not root or root == p or root == q:
return root
l = self.lowestCommonAncestor(root.left, p, q) # 左子树中 p, q 的LCA,返回值为None或节点
r = self.lowestCommonAncestor(root.right, p, q) # 右子树中 p, q 的LCA,返回值为None或节点
if l and r:
return root
return l or r # 短路原则。
4. 总结
关键能够发现:什么条件下这个点是LCA(Least Common Ancestors )。
5. 参考文献
[1] 剑指offer丛书
[2] 剑指Offer——名企面试官精讲典型编程题