從前序和中序遍歷序列中構造二叉樹

2021-10-03 13:10:42 字數 3320 閱讀 1233

其實是演算法題,各參考資料有對應題解,如leetcode-105,本文只是官方題解以及不同解法的解析比較,思想最重要,理解為最終目的,若有錯誤,懇請指正,詳情請參考原版,謝謝!!

1.力扣官方題解

官方題解的結構是有乙個工具方法處理所傳入的索引區間內的元素(找根並劃分左右),有點類似二分法查詢的思想,遞迴呼叫使得區間越來越小,直至為1;外層方法作為遞迴呼叫的乙個初始入口,呼叫後返回工具方法的執行結果。

class

solution

//選定preorder的第乙個元素為root

int root_val = preorder[pre_idx]

; treenode root =

newtreenode

(root_val)

;//root對應的元素在inorder中將序列一分為二:左子樹序列和右子樹序列

//從hashmap中獲取到root_val對應的索引,在中序序列中索引左即左子樹序列,右即右子樹序列部分

int index = idx_map.

get(root_val)

;//遞迴呼叫

pre_idx++

;//構建左子樹

root.left =

buildtool

(in_left,index)

;//構建右子樹

root.right =

buildtool

(index+

1,in_right)

;return root;

}//外層方法類,其呼叫treetool,然後treetool遞迴呼叫自身

public treenode buildtree

(int

preorder,

int[

]inorder)

return

buildtool(0

,inorder.length)

;//呼叫treetool,入參是中序序列的最大最小索引值,然後treetool遞迴呼叫自身,入參的區間大小逐步減小直至為1,即只有乙個元素

}}

2.題解

題解的結構與官方題解類似,但是更為精煉,其中遞迴構建左右子樹時候的第3個引數很關鍵,構建左子樹時,其根節點是preindex對應的元素,則由前序遍歷的性質,preindex+1對應的元素即preindex對應元素的左子,即左子樹構成的序列範圍內的『根節點』;構建右子樹時,其根節點通過計算可得:上一次處理得到根節點在中序序列的索引值為i,即前序序列除preindex後緊接著(i-infrom+1)個元素都是左子樹的元素,則右子樹構成的序列範圍內的『根節點』的索引值為preindex+i-infrom+1,這裡為什麼是i-infrom+1,是因為在中序序列中尋找根節點對應在中序序列中的索引值時是從infrom開始的,也即本次確定的左節點元素個數是i-infrom+1,這一點比較繞。

class

solution

//靜態方法,處理傳入的前序序列prelist、中序序列inlist,

//本次的根元素在前序序列中的索引preindex、本次所要處理的中序序列的索引區間上下限infrom,into

public

static treenode buildcore

(int

prelist,

int[

] inlist,

int preindex,

int infrom,

int into)

//以前序序列中可確定的preindex對應的元素為這一層的根構建樹結構

treenode root =

newtreenode

(prelist[preindex]);

for(

int i=infrom;ireturn root;

}}

3.題解

題解分析

入手是從前序序列的第乙個元素入手,該元素就是樹的根,拿著這個根元素的值,在中序序列中尋找對應索引,則找到索引左側為左子樹元素,右側為右子樹元素,兩邊的長度都好確定,這裡有用的是左子樹長度,由左子樹長度可得在前序序列中左子樹的結束索引和右子樹的起始索引,這樣資訊已足夠(確定了前序遍歷的上下索引,中序遍歷的上下索引),可進行遞迴呼叫了,即下邊方法中的buildnode入參

class

solution

return

buildnode

(preorder,

0,preorder.length-

1,inorder,

0,inorder.length-1)

;}private treenode buildnode

(int

preorder,

int prestart,

int preend,

int[

] inorder,

int instart,

int inend)

*///因前序遍歷陣列的第乙個元素為根,取前序遍歷的第乙個元素開始構建樹

int rootvalue = preorder[prestart]

; treenode root =

newtreenode

(rootvalue)

;//邊界情況處理:前序序列只有根節點,即只有乙個元素

if(prestart == preend)

//遍歷中序序列,找根節點,從instart開始

int rootinorder = instart;

while

(inorder[rootinorder]

!=rootvalue && rootinorder<=inend)

/*構建左右子樹*/

//獲取左子樹的長度,得到左子樹最後乙個元素的索引

int leftlength = rootinorder - instart;

//前序序列中左子樹的最後乙個元素索引(為迭代進buildnode的第三個入參)

//從中序序列可得根元素左子樹的元素個數leftlength,則由前序序列的性質(node->left->right)

//前序序列根元素node(第乙個元素)後leftlength個元素定全是根的左子樹元素,計算左子樹的結束索引

int leftpreend = prestart + leftlength;

//若左子樹非空,則遞迴構建

if(leftlength>0)

//若右子樹非空,則遞迴構建

if(leftlengthreturn root;

}}

從前序與中序遍歷序列構造二叉樹

題目描述 if inbegin inend 區間只有乙個結點,就是根結點 區間正常 int rootindex inbegin while rootindex inend 用前序的根劃分中序為兩個子區間 else 遞迴建立左子樹 root left buildtree preorder,pindex...

從前序與中序遍歷序列構造二叉樹

根據一棵樹的前序遍歷與中序遍歷構造二叉樹。注意 你可以假設樹中沒有重複的元素。例如,給出前序遍歷 preorder 3,9,20,15,7 中序遍歷 inorder 9,3,15,20,7 返回如下的二叉樹 3 9 20 15 7python definition for a binary tree...

從前序與中序遍歷序列構造二叉樹

根據一棵樹的前序遍歷與中序遍歷構造二叉樹。definition for a binary tree node.public class treenode class solution int rootidx left while rootidx right rootidx 前序 3 9 20 15 ...