contents解答輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。
例如,給出
前序遍歷 preorder = [3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]
返回如下的二叉樹:
3
/ \9 20
/ \
15 7
限制:0 <= 節點個數 <= 5000
引用題解區liweiwei大佬的乙個** 題解鏈結
找到當前樹的根節點。根節點一定是前序遍歷序列的第乙個,即上圖中的1。
找到根節點在中序遍歷序列當中的位置,即上圖中pivot指向的位置。
根據中序遍歷中根節點的位置,可以將整個inorder
陣列劃分為左子樹部分和右子樹部分,即綠色框和紅色框部分。
根據中序遍歷中左子樹部分的個數,反過來又可以把preorder
陣列劃分為左子樹部分和右子樹部分,即綠色框和紅色框部分。
以上的步驟將前序遍歷序列和中序遍歷序列劃分成為3部分
但是這還不足以重構整個二叉樹,因為這是個遞迴問題,還需要解決遞迴子問題
我們需要編寫遞迴函式來實現上述邏輯。
遞迴引數(函式簽名)
treenode recur(int prel,int prer,int inl,int inr)
遞迴終止條件
如果左邊界大於右邊界,表示當前的子樹沒有任何節點,是null
if(prel > prer || inl > inr) return null;
遞推過程
構建當前子樹的根節點root
,root
的值是preorder[prel]
在中序遍歷序列inorder
中尋找根節點root
的值所在的位置
根據上面的**,我們可以劃分出root
的左右子樹在兩個序列裡的範圍。得到root
的左右子樹的prel
,prer
,inl
,inr
。呼叫遞迴子函式,構造出root
的左右子樹。
返回值(回溯)
返回當前構建的root
子樹,成為更高一層遞迴函式中的左右子樹。
特殊輸入
以上情況都無法重建出乙個二叉樹,返回null
全域性變數
本**參考了liweiwei的實現。
class
solution
//開啟遞迴呼叫
return recur(0,prelen - 1,0,inlen - 1);
}//遞迴函式引數:
//prel,prer表示當前子樹在前序遍歷序列preorder當中的左右邊界
//inl,inr表示當前子樹在中序遍歷序列inorder當中的左右邊界
private treenode recur
(int prel,int prer,int inl,int inr)
}
本**參考了k神的實現**演算法資料結構。
仔細觀察,可以發現**1當中的prer
其實沒有用到,是乙個沒用的引數,可以直接把他去掉。
class
solution
//遞迴函式的引數實際上不需要inorder陣列,因為根本沒有用到
private treenode recur
(int preorder, int pre_lo, int in_lo, int in_hi)
}
遞迴函式引數設計的技巧從上面這題中可以總結出乙個設計遞迴函式引數的技巧,
時間複雜度:o(n)
空間複雜度:o(n)
劍指offer7 重建二叉樹
輸入一棵二叉樹前序遍歷和中序遍歷的結果,請重建該二叉樹。注意 二叉樹中每個節點的值都互不相同 輸入的前序遍歷和中序遍歷一定合法 樣例 給定 前序遍歷是 3,9,20,15,7 中序遍歷是 9,3,15,20,7 返回 3,9,20,null,null,15,7,null,null,null,null...
劍指offer7 重建二叉樹
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列和中序遍歷序列,則重建二叉樹並輸出它的頭節點。根據先序序列第乙個數確定樹的根節點,在中序序列中找到這個數所在的位置,此處左邊為左子樹,右邊為右子樹,根據遞迴建立二叉樹。...
劍指offer 7 重建二叉樹
因為各種各樣的原因,要開始準備春招,所以開始刷劍指offer 第二版 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列和中序遍歷序列,則重建二叉樹並返回。這個是個二叉樹很基礎的題啦,需要用遞迴來實現。主要講解在書的6...