給定一個二叉搜索樹, 找到該樹中兩個指定節點的最近公共祖先。node
後序遍歷法,將pq的公共父節點問題轉化爲找到一個節點node使得p、q分別位於node的左右子樹中;web
若p和q要麼分別位於左右子樹中,那麼對左右子結點調用遞歸函數,會分別返回p和q結點的位置,而當前結點正好就是p和q的最小共同父結點,直接返回當前結點便可。app
若p和q同時位於左子樹,這裏有兩種狀況,一種狀況是left會返回p和q中較高的那個位置,而right會返回空,因此咱們最終返回非空的left便可。還有一種狀況是會返回p和q的最小父結點,就是說當前結點的左子樹中的某個結點纔是p和q的最小父結點,會被返回。ide
若p和q同時位於右子樹,一樣這裏有兩種狀況,一種狀況是right會返回p和q中較高的那個位置,而left會返回空,因此咱們最終返回非空的right便可,還有一種狀況是會返回p和q的最小父結點,就是說當前結點的右子樹中的某個結點纔是p和q的最小父結點,會被返回。函數
只要找到其中的一個結點,就不會繼續往下找,好比同在左子樹上,也就是上面說到的第二點;spa
若是是分別在兩邊子樹上,那麼left和right就都可以找到,此時返回的就是他們的父親結點,也就是上面說到的第一點;code
找出兩個結點的路徑,對路徑中的值進行比對,直到出現不同的結點爲止;orm
# 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
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if not left:
return right
elif not right:
return left
return root
def lowestCommonAncestor(self, root, p, q):
"""
比對路徑
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
pathP, pathQ = self.findPath(root, p), self.findPath(root, q)
lenP, lenQ = len(pathP), len(pathQ)
ans, x = None, 0
# 找出出現不一致的結點,則上一個結點則爲最近公共結點
while x < min(lenP, lenQ) and pathP[x] == pathQ[x]:
ans, x = pathP[x], x + 1
return ans
def findPath(self, root, target):
"""
獲取結點的路徑
"""
stack = []
lastVisit = None
while stack or root:
if root:
stack.append(root)
root = root.left
else:
peek = stack[-1]
if peek.right and lastVisit != peek.right:
root = peek.right
else:
if peek == target:
return stack
lastVisit = stack.pop()
root = None
return stack