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——名企面試官精講典型編程題