輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。
例如,給出
前序遍歷 preorder = [3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]
返回如下的二叉樹:
3
/ \ 9
20/ \
157
限制:
0 <= 節點個數 <= 5000
思路:二叉樹的前序遍歷順序是:根節點、左子樹、右子樹,每個子樹的遍歷順序同樣滿足前序遍歷順序。
二叉樹的中序遍歷順序是:左子樹、根節點、右子樹,每個子樹的遍歷順序同樣滿足中序遍歷順序。
前序遍歷的第乙個節點是根節點,只要找到根節點在中序遍歷中的位置,在根節點之前被訪問的節點都位於左子樹,在根節點之後被訪問的節點都位於右子樹,由此可知左子樹和右子樹分別有多少個節點。
由於樹中的節點數量與遍歷方式無關,通過中序遍歷得知左子樹和右子樹的節點數量之後,可以根據節點數量得到前序遍歷中的左子樹和右子樹的分界,因此可以進一步得到左子樹和右子樹各自的前序遍歷和中序遍歷,可以通過遞迴的方式,重建左子樹和右子樹,然後重建整個二叉樹。
使用乙個 map 儲存中序遍歷的每個元素及其對應的下標,目的是為了快速獲得乙個元素在中序遍歷中的位置。呼叫遞迴方法,對於前序遍歷和中序遍歷,下標範圍都是從 0 到 n-1,其中 n 是二叉樹節點個數。
遞迴方法的基準情形有兩個:判斷前序遍歷的下標範圍的開始和結束,若開始大於結束,則當前的二叉樹中沒有節點,返回空值 null。若開始等於結束,則當前的二叉樹中恰好有乙個節點,根據節點值建立該節點作為根節點並返回。
若開始小於結束,則當前的二叉樹中有多個節點。在中序遍歷中得到根節點的位置,從而得到左子樹和右子樹各自的下標範圍和節點數量,知道節點數量後,在前序遍歷中即可得到左子樹和右子樹各自的下標範圍,然後遞迴重建左子樹和右子樹,並將左右子樹的根節點分別作為當前根節點的左右子節點。
/**
* definition for a binary tree node.
* public class treenode
* }*/class
solution
treenode tr =
buildtree
(preorder,
0,length-
1,inorder,
0,length-
1,indexmap)
;return tr;
}public treenode buildtree
(int
preorder,
int preorderstart,
int preorderend,
int[
] inorder,
int inorderstart,
int inorderend,map
indexmap)
int rootval = preorder[preorderstart]
; treenode root =
newtreenode
(rootval);if
(preorderstart == preorderend)
else
}}
時間複雜度:o(n)。
空間複雜度:o(n)。
二叉樹 重建二叉樹
問題 給定二叉樹的前序遍歷結果和中序遍歷結果,恢復出原二叉樹。假設二叉樹中的元素都不重複,給定二叉樹的前序遍歷序列,二叉樹的中序遍歷序列。看到此題,我首先想到的是尋找根節點,由前序遍歷序列可以看出根節點為1,此時通過中序遍歷可以看出來4,7,2在根節點的左子樹,5,3,8,6在樹的右節點。此時我們可...
二叉樹 重建二叉樹
題目給定兩個陣列,乙個是前序遍歷陣列 preorder 乙個是中序遍歷陣列 inorder 要求輸出還原二叉樹 核心在於我們要理解前序和中序便利的特點 前序遍歷 根節點 左節點 右節點 中序遍歷 左節點 根節點 右節點 所以我們從二叉樹的根節點開始重構 也就是preorder的第乙個值 同時用乙個m...
二叉樹重建
摘自劉汝佳的 演算法競賽入門經典 preorder t t 的根結點 preorder t 的左子樹 preorder t 的右子樹 inorder t inorder t 的左子樹 t 的根結點 inorder t 的右子樹 postorder t postorder t 的左子樹 postord...