本題知識點:樹
題目描述:
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。
例如,給出
前序遍歷 preorder = [3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]
返回如下的二叉樹:3/
9 20
/ 15 7
解題思路:
用前序遍歷找到根結點。
用根結點在中序遍歷中切開左右子樹,遞迴重建二叉樹。
方法:分治思想
經驗總結:二叉樹的問題一般都是分治思想,遞迴去做。因為二叉樹本身就是遞迴定義的。
題目分析:
前序遍歷特點: 節點按照 [ 根節點 | 左子樹 | 右子樹 ] 排序,以題目示例為例:[ 3 | 9 | 20 15 7 ]
中序遍歷特點: 節點按照 [ 左子樹 | 根節點 | 右子樹 ] 排序,以題目示例為例:[ 9 | 3 | 15 20 7 ]
根據題目描述輸入的前序遍歷和中序遍歷的結果中都不含重複的數字,其表明樹中每個節點值都是唯一的。
根據以上特點,可以按順序完成以下工作:
前序遍歷的首個元素即為根節點 root的值;
在中序遍歷中搜尋根節點 root 的索引 ,可將中序遍歷劃分為 [ 左子樹 | 根節點 | 右子樹 ] 。
根據中序遍歷中的左(右)子樹的節點數量,可將前序遍歷劃分為 [ 根節點 | 左子樹 | 右子樹 ] 。
自此可確定 三個節點的關係 :1.樹的根節點、2.左子樹根節點、3.右子樹根節點(即前序遍歷中左(右)子樹的首個元素)。
子樹特點: 子樹的前序和中序遍歷仍符合以上特點,以題目示例的右子樹為例:前序遍歷:[20 | 15 | 7],中序遍歷 [ 15 | 20 | 7 ] 。
根據子樹特點,我們可以通過同樣的方法對左(右)子樹進行劃分,每輪可確認三個節點的關係 。此遞推性質讓我們聯想到用 遞迴方法 處理。
遞迴解析:
遞推引數: 前序遍歷中根節點的索引pre_root、中序遍歷左邊界in_left、中序遍歷右邊界in_right。
終止條件: 當 in_left > in_right ,子樹中序遍歷為空,說明已經越過葉子節點,此時返回 nullnull 。
遞推工作:
建立根節點root: 值為前序遍歷中索引為pre_root的節點值。
搜尋根節點root在中序遍歷的索引i: 為了提公升搜尋效率,本題解使用雜湊表 dic 預儲存中序遍歷的值與索引的對映關係,每次搜尋的時間複雜度為 o(1)o(1) 。
構建根節點root的左子樹和右子樹: 通過呼叫 recur() 方法開啟下一層遞迴。
左子樹: 根節點索引為 pre_root + 1 ,中序遍歷的左右邊界分別為 in_left 和 i - 1。
右子樹: 根節點索引為 i - in_left + pre_root + 1(即:根節點索引 + 左子樹長度 + 1),中序遍歷的左右邊界分別為 i + 1 和 in_right 。
返回值: 返回 root ,含義是當前遞迴層級建立的根節點 root 為上一遞迴層級的根節點的左或右子節點。
**如下:
self.dic, self.po =
, preorder
for i in
range
(len
(inorder)):
self.dic[inorder[i]
]= i
return self.recur(0,
0,len(inorder)-1
)def
recur
(self, pre_root, in_left, in_right)
:if in_left > in_right:
return
# 終止條件:中序遍歷為空
root = treenode(self.po[pre_root]
)# 建立當前子樹的根節點
i = self.dic[self.po[pre_root]
]# 搜尋根節點在中序遍歷中的索引,從而可對根節點、左子樹、右子樹完成劃分。
root.left = self.recur(pre_root +
1, in_left, i -1)
# 開啟左子樹的下層遞迴
root.right = self.recur(i - in_left + pre_root +
1, i +
1, in_right)
# 開啟右子樹的下層遞迴
return root # 返回根節點,作為上層遞迴的左(右)子節點
4 劍指offer 重建二叉樹
樹 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列和中序遍歷序列,則重建二叉樹並返回。definition for binary tree struct treenode class solution vector...
劍指offer 重建二叉樹
重建二叉樹2.cpp 定義控制台應用程式的入口點。題目描述 輸入乙個二叉樹的前序遍歷和中序遍歷,輸出這顆二叉樹 思路 前序遍歷的第乙個節點一定是這個二叉樹的根節點,這個節點將二叉樹分為左右子樹兩個部分,然後進行遞迴求解 include stdafx.h include vector using na...
《劍指offer》重建二叉樹
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如,則重建二叉樹並返回。輸入乙個樹的前序和中序,例如輸入前序遍歷序列和中序遍歷序列 根據輸入的前序和中序,重建乙個該二叉樹,並返回該樹的根節點。definition for binary...