236. 二叉樹的最近公共祖先

236. 二叉樹的最近公共祖先

題意

給定一個二叉搜索樹, 找到該樹中兩個指定節點的最近公共祖先。node

解題思路

  1. 後序遍歷法,將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的最小父結點,會被返回。函數

    1. 只要找到其中的一個結點,就不會繼續往下找,好比同在左子樹上,也就是上面說到的第二點;spa

    2. 若是是分別在兩邊子樹上,那麼left和right就都可以找到,此時返回的就是他們的父親結點,也就是上面說到的第一點;code

  1. 找出兩個結點的路徑,對路徑中的值進行比對,直到出現不同的結點爲止;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
相關文章
相關標籤/搜索