題目描述
根據一棵樹的前序遍歷與中序遍歷構造二叉樹。
注意:
你可以假設樹中沒有重複的元素。
例如,給出
前序遍歷 preorder = [3,9,20,15,7]返回如下的二叉樹:中序遍歷 inorder = [9,3,15,20,7]
3樹的儲存結構:/ \
9 20
/ \
15 7
public
class
treenode
treenode
(int val)
treenode
(int val, treenode left, treenode right)
}
解題思路:
題意容易理解,根據給出的前序和中序遍歷構造出對應的二叉樹。我們只需要知道前序和中序遍歷的過程即可。
//樹的前序遍歷
private
void
preorder
(treenode root)
}//樹的中序遍歷
private
void
preorder
(treenode root)
}
通過以上兩段**我們可以發現:
1.前序遍歷時,當根結點不為空時,先列印root.val,再遞迴遍歷root.left,再遞迴遍歷root.right.因此,前序遍歷結果集的第乙個元素即為根結點。
2.中序遍歷時,當根結點不為空時,先遞迴遍歷root.left,再列印當前結點root.val,再遞迴遍歷右子樹。因此,在中序遍歷結果集中,左子樹中的元素都在根結點左邊,右子樹中的元素都在根結點右邊。
根據以上兩個特點,我們可以在前序遍歷結果集和中序遍歷結果集中,首先找出前序遍歷結果集中的第乙個元素,即為當前根結點
。然後再從中序遍歷結果集中找出根結點對應的下標,此時將中序遍歷結果集分成兩部分,根結點左側為左子樹遍歷結果集,根結點右側為右子樹遍歷結果集,我們可以知曉左右子樹結果集的元素個數。然後再根據前序遍歷
的特點,即先遍歷左子樹再遍歷右子樹,因此左子樹前序遍歷結果集在右子樹前序遍歷結果集前。結合左右子樹結果集元素個數,將前序遍歷結果集分成兩部分,分別是左子樹前序遍歷結果集和右子樹前序遍歷結果集。
此時,我們便將問題的規模變小使得可以運用遞迴來解決問題。
class
solution
return
mybuildtree
(preorder,
0,preorder.length,inorder,
0,memo);}
//構建二叉樹
//preorder是前序序遍歷結果集
//pbegin,pend 分別是preorder的起點下標與終點下標,左閉右開
//ibegin是inorder的起始下標,用於協助分割前序遍歷的結果集
//memo用於儲存中序遍歷結果集的元素下標
private treenode mybuildtree
(int
preorder,
int pbegin,
int pend,
int ibegin,map
memo)
return null;
}}
注意:
需要理解pbegin < pend
的含義;首先,使用map獲取到前序首元素在中序遍歷中的位置,然後index - ibegin
即為左子樹元素的個數。當其值為零時,就代表左子樹為空。而此時pbegin + 1
與pbegin + 1 + index - ibegin
的值相同,在遞迴便會返回null。右子樹為空時同理。不過這樣理解起來還是會有點困難,可以簡單的理解成[pbegin,pend)
左閉右開,表示還未納入樹中的結點區間範圍。當pbegin >= pend
時,此時範圍非法,表示所有結點已經納入樹中,因此返回null。否則就返回當前結點,並且遞迴的納入其子結點。
105 從前序與中序遍歷序列構造二叉樹
如題,根據前序與中序遍歷序列構造二叉樹 整體思路 前序遍歷的第乙個元素,必然是二叉樹的根節點 在中序遍歷中找到前序遍歷第乙個元素的位置 該位置左邊的所有點都是二叉樹的左子樹元素,該位置右邊的所有點都是二叉樹的右子樹元素 思路一 遞迴 字典 由整體思路可以構建子函式用於遞迴,不斷求子樹的左右子樹,直到...
105 從前序與中序遍歷序列構造二叉樹
根據一棵樹的前序遍歷與中序遍歷構造二叉樹。注意 你可以假設樹中沒有重複的元素。例如,給出 前序遍歷 preorder 3,9,20,15,7 中序遍歷 inorder 9,3,15,20,7 返回如下的二叉樹 3 9 20 15 7 def buildtree2 preorder,inorder i...
105 從前序與中序遍歷序列構造二叉樹
根據一棵樹的前序遍歷與中序遍歷構造二叉樹。注意 你可以假設樹中沒有重複的元素。例如,給出 前序遍歷 preorder 3 9,20 15,7 中序遍歷 inorder 9 3,15 20,7 返回如下的二叉樹 3 9 20 157前序與中序遍歷的序列有乙個特點 對於某棵樹來講,先序遍歷的序列的長度與...