題目:輸入某二叉樹的前序周遊和中序周遊的結果,請重建出該二叉樹。假設輸入的前序周遊和中序周遊的結果中都不含重複的數字。例如輸入前序周遊序列{1,2,4,7,3,5,6,8}和中序周遊序列{4,7,2,1,5,3,8,6},則重建二叉樹并傳回。
思路:已知一棵樹的先序周遊的結果數組和中序周遊的結果,要求據此重建一棵二叉樹,即重建所有結點并設定結點之間的指針關系,最後傳回這棵樹的根結點。分析二叉樹的前序周遊和中序周遊的特征。
先序周遊:①[②④⑦][③⑤⑥⑧]
中序周遊:[④⑦②]①[⑤③⑧⑥]
對于先序周遊的數組arr1[begin,end],第一個元素就是數組對應樹的根結點,顯然①是根結點,然後根據值1周遊中序數組arr2,已知元素不重複,是以可以找到唯一的元素,找到其在arr2中的位置為i,此時arr2中[begin,i-1]是結點①的左子樹對應的數組,[i+1,end]是結點①的右子樹對應的數組,分别求出這2個子數組的長度length1=i-1-begin+1=i-begin;length2=end-i-1+1=end-i。然後取先序數組arr1中找出對應的子數組,分别是[begin+1,begin+length1],[begin+lenght1+1,end],于是得到了:
用來建構結點①左子樹所需的先序數組和中序數組arr1[begin+1,begin+length1]+arr2[begin,i-1];
用來建構結點①右子樹所需的先序數組和中序數組arr2[begin+lenght1+1,end]+arr2[i+1,end];
于是問題有回到了原始的問題上面來了,調用遞歸方法分别出入這2個數組以及邊界,傳回建立起來的二叉樹的頭結點,然後将其與目前結點arr1[begin]連接配接起來即可。
邊界條件是:如果數組對于arr1數組或者arr2數組,有begin<end,那麼說明此時對應的樹為null,直接傳回null即可。
F⑤:tempNode是方法體内部的局部變量,隻在本方法中有效,于是當遞歸傳回到上一層後目前的tempNode就失效了,是以不能直接在上一層的方法中通路tempNode來擷取之前的tempNode,但是使用傳回是正确的,每次tempNode隻需要在本層方法中起作用,所得結果會傳回給上一層的方法,傳回之前會為其關聯上子樹對象,于是傳回的結點總是帶着子樹的,越往上傳回子樹越大,直到最後傳回的是一棵完整的二叉樹,是以這裡不需要講tempNode設定成為全局或者成員變量。
//輸入二叉樹的先序和中序數組,重建二叉樹傳回樹的頭結點
publicclass Solution {
public TreeNode reConstructBinaryTree(int[] pre,int [] in) {
//特殊輸入
if(pre.length!=in.length||pre.length<=0)return null;
//調用遞歸函數解決問題并傳回頭結點
returnthis.process(pre,0,pre.length-1,in,0,in.length-1);
}
//遞歸函數:傳入二叉樹的先序和中序周遊的數組或者數組區間,傳回建構的二叉樹的頭結點
private TreeNode process(int[] arr1,intbegin1,int end1,int[] arr2,int begin2,int end2){
//關鍵:邊界條件,如果begin=end最終也會變成begin>end
if(begin1>end1||begin2>end2)return null;
//①先找根結點
int val=arr1[begin1];
//②找到val在中序數組arr2中的位置i
int i=this.getIndexInArr2(arr2,val);
//③求出中序數組中2個區間的長度
int length1=i-begin2;
int length2=end2-i;
//④找出先序數組中對應的數組
TreeNodeleftNode=this.process(arr1,begin1+1,begin1+length1,arr2,begin2,i-1);
TreeNode rightNode=this.process(arr1,begin1+length1+1,end1,arr2,i+1,end2);
//F⑤建立目前結點并将其與左右結點連接配接
TreeNodetempRoot=new TreeNode(val);
tempRoot.left=leftNode;
tempRoot.right=rightNode;
//傳回建立二叉樹的根結點
return tempRoot;
}
//函數:根據值val在數組中找到對應的下标
private int getIndexInArr2(int[] arr,intval){
int res=0;
for(int i=0;i<arr.length;i++){
if(arr[i]==val) res=i;
}
return res;
}
}