方法二:遞迴--雜湊表
例如要重建的是如下二叉樹。
其前序遍歷和中序遍歷如下。
preorder = [3,9,8,5,4,10,20,15,7]前序遍歷的第乙個元素 3 是根節點,第二個元素 9 可能位於左子樹或者右子樹,需要通過中序遍歷判斷。inorder = [4,5,8,10,9,3,15,20,7]
中序遍歷的第乙個元素是 4 ,不是根節點 3,說明 9 位於左子樹,因為根節點不是中序遍歷中的第乙個節點。同理,前序遍歷的後幾個元素 8、5、4 也都位於左子樹,且每個節點都是其上乙個節點的左子節點。
前序遍歷到元素 4,和中序遍歷的第乙個元素相等,說明前序遍歷的下乙個元素 10 位於右子樹。那麼 10 位於哪個元素的右子樹?從前序遍歷看,10 可能位於 4、5、8、9、3 這些元素中任何乙個元素的右子樹。從中序遍歷看,10 在 8 的後面,因此 10 位於 8 的右子樹。把前序遍歷的順序反轉,則在 10 之前的元素是 4、5、8、9、3,其中 8 是最後一次相等的節點,因此前序遍歷的下乙個元素位於中序遍歷中最後一次相等的節點的右子樹。
同理可知,20 位於 3 的右子樹,15 和 7 分別是 20 的左右子節點。
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。
例如,給出
前序遍歷 preorder = [3,9,20,15,7]前序遍歷特點: 節點按照 [ 根節點 | 左子樹 | 右子樹 ] 排序,以題目示例為例:[ 3 | 9 | 20 15 7 ]中序遍歷 inorder = [9,3,15,20,7]
中序遍歷特點: 節點按照 [ 左子樹 | 根節點 | 右子樹 ] 排序,以題目示例為例:[ 9 | 3 | 15 20 7 ]
根據題目描述輸入的前序遍歷和中序遍歷的結果中都不含重複的數字,其表明樹中每個節點值都是唯一的。
根據以上特點,可以按順序完成以下工作:
前序遍歷的首個元素即為根節點 root 的值;
在中序遍歷中搜尋root 的索引 ,並劃分為 [ 左子樹 | 根節點 | 右子樹 ]。
根據中序遍歷中的左(右)子樹的節點數量,可將前序遍歷劃分為 [ 根節點 | 左子樹 | 右子樹 ] 。
自此可確定三個節點的關係 :
1.樹的根節點即前序遍歷中左右子樹的首個元素。2.左子樹根節點
3.右子樹根節點
子樹特點: 子樹的前序和中序遍歷仍符合以上特點,以題目示例的右子樹為例:前序遍歷:[20 | 15 | 7],中序遍歷 [ 15 | 20 | 7 ] 。
根據子樹特點,我們可以通過同樣的方法對左右子樹進行劃分,每輪可確認三個節點的關係 。此遞推性質讓我們聯想到用遞迴方法 處理。
class
solution
:def
buildtree
(self, preorder: list[
int]
, inorder: list[
int])-
> treenode:
iflen
(inorder)==0
:return
none
#獲取根節點
root=treenode(preorder[0]
)#獲取根節點在中序遍歷中的索引
idx=inorder.index(preorder[0]
)#左子樹,由idx可得左子樹長度為idx,前序遍歷中第乙個為root,因此preorder[1:idx+1]為左子樹部分,剩餘的為右子樹
root.left=self.buildtree(preorder[
1:idx+1]
,inorder[
:idx]
)#右子樹
root.right=self.buildtree(preorder[idx+1:
],inorder[idx+1:
])return root
建立根節點root: 值為前序遍歷中索引為pre_root的節點值。
搜尋根節點root在中序遍歷的索引i:使用雜湊表 dic 預儲存中序遍歷的值與索引的對映關係,每次搜尋的時間複雜度為 o(1),提公升搜尋效率。
class
solution
:def
buildtree
(self, preorder: list[
int]
, inorder: list[
int])-
> treenode:
self.dic,self.preorder=
,preorder
#for index,item in enumerate(inorder):
# self.dic[item]=index
for i in
range
(len
(inorder)):
self.dic[inorder[i]]=i
return self.recur(0,
0,len(inorder)-1
)def
recur
(self,pre_root,left,right)
:if left>right:
return
root=treenode(self.preorder[pre_root]
) i=self.dic[self.preorder[pre_root]
] root.left = self.recur(pre_root +
1, left , i -1)
root.right = self.recur(pre_root +
1+ i - left , i +
1, right)
return root
LeetCode 演算法學習 2
longest substring without repeating characters given a string,find the length of the longest substring without repeating characters.example 1 input ab...
演算法函式 演算法學習筆記 18 尤拉函式
數論中的尤拉函式 對於尤拉函式,主要有如下性質 我們來證明第乙個性質 在不大於 不與之互質的只有 至於第二個性質,設那 第三個性質的證明需要用到複雜一些的數論知識,這裡不證了,可參見這篇部落格。符合這種性質的數論函式稱為積性函式。我們把正整數質因數分解 所有 兩兩互質,由尤拉函式的性質有 即 用這個...
Leetcode演算法學習日誌 78 Subsets
given a set ofdistinctintegers,nums,return all possible subsets the power set note the solution set must not contain duplicate subsets.for example,ifn...