輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
輸出: 3
解釋: 節點 5 和節點 1 的最近公共祖先是節點 3。
class
bintnode
:def
__init__
(self,data=
none
,left =
none
,right =
none):
self.data =data
self.left =left
self.right =right
defbuildtree1
(arr,pointer,n)
:if pointer <=n:
if arr[pointer]==-
1:curnode =
none
else
: curnode = bintnode(arr[pointer])if
2*pointer+
1<=n:
curnode.left = buildtree(arr,
2*pointer+
1,n)if2
*pointer+
2<=n:
curnode.right = buildtree(arr,
2*pointer+
2,n)
return curnode
# 如下是簡化的版本,我們一般在迴圈裡盡量少用判斷語句
defbuildtree
(arr,pointer,n)
:# 遞迴出口,當越界時就沒有必要建立節點了直接return,開始回退
# 當值為-1時,也沒有必要建立結點
if pointer > n or arr[pointer]==-
1:return
none
curnode = bintnode(arr[pointer]
) curnode.left = buildtree(arr,
2*pointer+
1,n)
curnode.right = buildtree(arr,
2*pointer+
2,n)
return curnode
def
findancestor
(root,child1,child2):if
not root:
return-1
# 把原問題分成三個部分,左子樹,當前結點,右子樹
if root.data == child1 or root.data ==child2:
# 不管下面還有沒有要找的child,整顆樹的祖先都是root
return root.data
# 如果root不是任何乙個的祖先,就需要處理下面的2顆子樹
left_ancestor = findancestor(root.left,child1,child2)
right_ancestor = findancestor(root.right,child1,child2)
# 然後基於兩顆子樹得到的結果處理,分為六種情況:
# 左0右0,-1, left_ancestor + right_ancestor + 1
# 左1右1,root.data, root.data
# 左1右0,left_ancestor left_ancestor + right_ancestor + 1
# 左0右1,right_ancestor left_ancestor + right_ancestor + 1
# 左2右0,left_ancestor left_ancestor + right_ancestor + 1
# 左0右2,right_ancestor left_ancestor + right_ancestor + 1
if left_ancestor !=-1
and right_ancestor !=-1
:return root.data
# 這個簡化處理非常巧妙,一般寫迴圈盡量少用判斷,可以巧妙利用返回值-1構造通用結果
# 看這個處理直接把其他的5種結果都處理成left_ancestor + right_ancestor + 1
# 利用返回的結果為-1,+1之後可以消除可能出現的那個結果
return left_ancestor + right_ancestor +
1# 這種方案存在問題,當一顆子樹只含有child1時,
# 那麼這顆子樹的祖先就是child1,一顆子樹只含有child2時,那麼這顆子樹的祖先就是child2,
# 但是最終方案是求共同祖先,如果輸入乙個孩子不存在,那返回結果不久變成了兩外乙個孩子
deffindancestor2
(root,child1,child2)
:# 把原問題分成三個部分,左子樹,當前結點,右子樹if(
not root)
or root.data == child1 or root.data ==child2:
# 不管下面還有沒有要找的child,整顆樹的祖先都是root
return root
# 如果root不是任何乙個的祖先,就需要處理下面的2顆子樹
# left_ancestor =none
# right_ancestor =none
left_ancestor = findancestor2(root.left,child1,child2)
right_ancestor = findancestor2(root.right,child1,child2)
# 然後基於兩顆子樹得到的結果處理,分為六種情況:
# 左0右0,none, [left_ancestor , right_ancestor]
# 左1右1,root, root
# 左1右0,left_ancestor [left_ancestor , right_ancestor]
# 左0右1,right_ancestor [left_ancestor , right_ancestor ]
# 左2右0,left_ancestor [left_ancestor , right_ancestor]
# 左0右2,right_ancestor [left_ancestor , right_ancestor]
if left_ancestor and right_ancestor:
return root
# 這個簡化處理非常巧妙,一般寫迴圈盡量少用判斷,可以巧妙利用返回值-1構造通用結果
# 看這個處理直接把其他的5種結果都處理成left_ancestor + right_ancestor + 1
# 利用返回的結果為-1,+1之後可以消除可能出現的那個結果
return
(left_ancestor,right_ancestor)
[not left_ancestor]
# leetcode 236
# 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, p, q)
:"""
:type root: treenode
:type p: treenode
:type q: treenode
:rtype: treenode
"""if(
not root)
or root.data == p or root.data ==q:
return root
left_ancestor = self.lowestcommonancestor(root.left,p,q)
right_ancestor = self.lowestcommonancestor(root.right,p,q)
if left_ancestor and right_ancestor:
return root
# 比較三種情況的處理
return left_ancestor if left_ancestor else right_ancestor
arr =[1
,2,3
,4,5
,6,7
,-1,
-1,8
,9,-
1,-1
,10,11
]root = buildtree(arr,0,
len(arr)-1
)print
(findancestor(root,9,
5))print
(findancestor2(root,9,
5).data)
print
(solution(
).lowestcommonancestor(root,9,
5).data)
runfile(
'd:/share/test/buildtree.py'
, wdir=
'd:/share/test')5
55
高頻演算法面試題學習總結 樹形結構2 共同祖先
題目 有個二叉樹,還有倆節點,如何找得到,最近的祖先 輸入 root value1 5 value2 6 解釋 1 2 3 null 4 5 6 root對應的是乙個樹形結構,1代表null,正整數代表這個節點的值,每個節點的值全域性唯一。輸出 3 思路1 對二叉樹進行dfs遍歷,記錄每個節點為根的...
leetcode 首個共同祖先
設計並實現乙個演算法,找出二叉樹中某兩個節點的第乙個共同祖先。不得將其他的節點儲存在另外的資料結構中。注意 這不一定是二叉搜尋樹。例如,給定如下二叉樹 root 3,5,1,6,2,0,8,null,null,7,4 3 5 1 6 2 0 8 7 4 遞迴中止條件 如果當前查詢的節點是空的那麼函式...
leetcode 首個共同祖先 遞迴
設計並實現乙個演算法,找出二叉樹中某兩個節點的第乙個共同祖先。不得將其他的節點儲存在另外的資料結構中。注意 這不一定是二叉搜尋樹。例如,給定如下二叉樹 root 3,5,1,6,2,0,8,null,null,7,4 3 5 1 6 2 0 8 7 4 示例 1 輸入 root 3,5,1,6,2,...