重建二叉樹
題目描述
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。 |
思路1
- 在二叉樹的前序遍歷序列中,第一個數字老是樹的根節點的值。但在中序遍歷序列中,根節點的值在序列的中間,左子樹的節點值位於根節點的值的左邊,而右子樹的節點的值位於根節點的值的右邊。
- 例如:
前序序列{1,2,4,7,3,5,6,8} = pre
中序序列{4,7,2,1,5,3,8,6} = in
- 根據當前前序序列的第一個結點肯定根結點,爲 1;
- 找到 1 在中序遍歷序列中的位置,爲 in[3];
- 切割左右子樹,則 in[3] 前面的爲左子樹, in[3] 後面的爲右子樹;
- 則切割後的左子樹前序序列爲:{2,4,7},切割後的左子樹中序序列爲:{4,7,2};切割後的右子樹前序序列爲:{3,5,6,8},切割後的右子樹中序序列爲:{5,3,8,6};
- 對子樹分別使用一樣的方法分解。
程序(java)
/**
* code1:遞歸(傳入數組的拷貝)
* 時間複雜度:O(n),空間複雜度:O(n)
*/
import java.util.Arrays;
public static TreeNode reConstructBinaryTree(int[] pre, int[] in) {
if (pre == null || in == null || pre.length == 0 || in.length == 0) {
return null;
}
if (pre.length != in.length) {
return null;
}
TreeNode root = new TreeNode(pre[0]);
for (int i = 0; i < pre.length; i++) {
if (pre[0] == in[i]) {
root.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(in, i + 1, in.length));
}
}
return root;
}
複製代碼
/**
* code2:遞歸(傳入子數組的邊界索引)
* 時間複雜度:O(n),空間複雜度:O(n)
*/
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre == null || pre.length == 0 ||
in == null || in.length == 0) return null;
return helper(pre, 0, pre.length - 1, in, 0, in.length - 1);
}
private TreeNode helper(int[] pre, int preL, int preR, int[] in, int inL, int inR) {
if (preL > preR || inL > inR) {
return null;
}
int rootVal = pre[preL];
int index = 0;
while (index <= inR && in[index] != rootVal) {
index++;
}
TreeNode root = new TreeNode(rootVal);
root.left = helper(pre, preL + 1, preL - inL + index, in, inL, index);
root.right = helper(pre, preL - inL + index + 1, preR, in, index + 1, inR);
return root;
}
}
複製代碼
補充
關於Java中的Arrays.copyOfRange()方法
- 要使用這個方法,首先要import java.util.Arrays;
- 將一個原始的數組original,從下標from開始複製,複製到上標to,生成一個新的數組(8大類型基本數組)。注意這裏包括下標from,不包括上標to。
Arrays.copyOfRange(T[ ] original,int from,int to)
複製代碼
- 實例:
int [] s1 = {1,2,3,4,5};
int [] s2 = Arrays.copyOfRange(s1, 2, 4);
System.out.println(Arrays.toString(s2));
複製代碼
輸出 [3,4]
複製代碼
int [] s1 = {1,2,3,4,5};
int [] s2 = Arrays.copyOfRange(s1, 2, 5);
System.out.println(Arrays.toString(s2));
複製代碼
輸出 [3,4,5]
複製代碼
int [] s1 = {1,2,3,4,5};
int [] s2 = Arrays.copyOfRange(s1, 2, 2);
System.out.println(Arrays.toString(s2));
複製代碼
輸出 []
複製代碼
int [] s1 = {1,2,3,4,5};
int [] s2 = Arrays.copyOfRange(s1, 5, 5);
System.out.println(Arrays.toString(s2));
複製代碼
輸出 []
複製代碼
參考
- 數據結構之二叉樹
- 重建二叉樹(牛客網)
- 重建二叉樹(GitHub)