【劍指offer】重建二叉樹 ★★★
阿新 • • 發佈:2018-11-25
題目描述:
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
解題思路:
知道整體思路是:
在二叉樹的前序遍歷序列中,第一個數字總是樹的根結點的值。但在中序遍歷序列中,根結點的值在序列的中間,左子樹的結點的值位於根結點的值的左邊,而右子樹的結點的值位於根結點的值的右邊。因此我們需要掃描中序遍歷序列,才能找到根結點的值。如題目給出的序列,前序遍歷中的第一個數字1就是根結點的值。掃描中序遍歷序列,就能確定根結點的值的位置。根據中序遍歷的特點,在根結點的值1前面的3個數字都是左子樹結點的值,位於1後面的數字都是右子樹結點的值。這樣我們就在前序遍歷和中序遍歷兩個序列中,分別找到了左右子樹對應的子序列。因此,可以用同樣的方法去構建左右子樹。也就是說,接下來的事情可以用遞迴的方法去完成。
也就是在前序遍歷序列中找根節點,然後根據根節點到中序遍歷序列中劃分左右子樹兩部分,然後分別在左右子樹中遞迴重複上述過程。
但是每次一遇到遞迴問題思路就好亂啊,腦子完全纏繞在一起理不清啊啊啊~~~
所以,我就每次在做題之前都先把思路畫一畫,這樣寫程式的時候就清楚一些了:
public class Solution { public TreeNode reConstructBinaryTree(int [] pre,int [] in) { TreeNode root = new TreeNode(pre[0]); int len = pre.length; if(len == 1){ root.left = null; root.right = null; return root; } else { // 在中序遍歷序列中找到根節點的位置i int i; for (i=0;i<len;i++){ if (in[i] == root.val) break; } //左子樹,從pre[1]開始 int [] lpre = new int[i]; int [] lin = new int [i]; if(i == 0){ //當前中序序列的第一個為根節點,即不存在有左節點 root.left = null; } else{ for (int j=0;j<i;j++){ lpre[j] = pre[j+1]; lin[j] = in[j]; } root.left = reConstructBinaryTree(lpre,lin); } //右子樹,從pre[i+1]開始 int [] rpre = new int[len-i-1]; int [] rin = new int[len-i-1]; if (len-i-1 == 0){ //當前中序序列的最後一個為根節點,即不存在有右節點 root.right = null; } else{ for (int j=0;j<len-i-1;j++){ rpre[j] = pre[j+i+1]; rin[j] = in[j+i+1]; } root.right = reConstructBinaryTree(rpre,rin); } return root; } }