樹形結構 尋找共同祖先

2021-09-05 07:12:24 字數 4928 閱讀 9993

輸入: 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,...