1、邏輯梳理
1、後序遍歷的特點:後序遍歷的最後一個節點是根節點
2、中序遍歷的特點:根節點將中序序列分成左子樹和右子樹兩部分
具體步驟
1、從後序遍歷序列的最後一個節點取出根節點
2、在中序遍歷序列中找到根節點的位置,這個位置的左邊部分是左子樹,右邊部分是右子樹
3、遞歸構建左子樹和右子樹,重複以上步驟
注意 : 需要先構建右子樹,因為後序遍歷是左、右、根;逆序過來是需要根、右、左
2、核心代碼
public class BinaryTreeBuilder {
private Map<Integer, Integer> inorderIndexMap;
private int postIndex;
public TreeNode buildTree(int[] inorder, int[] postorder) {
// 構建中序遍歷值和索引的映射,方便快速查找根節點的位置
inorderIndexMap = new HashMap<>();
for (int i = 0; i < inorder.length; i++) {
inorderIndexMap.put(inorder[i], i);
}
postIndex = postorder.length - 1; // 初始化後序遍歷的根節點索引
return buildTreeHelper(postorder, 0, inorder.length - 1);
}
private TreeNode buildTreeHelper(int[] postorder, int inorderStart, int inorderEnd) {
// 遞歸終止條件
if (inorderStart > inorderEnd) {
return null;
}
// 從後序遍歷中獲取當前根節點
int rootVal = postorder[postIndex--];
TreeNode root = new TreeNode(rootVal);
// 在中序遍歷中找到根節點的索引
int inorderRootIndex = inorderIndexMap.get(rootVal);
// 遞歸構建右子樹和左子樹
root.right = buildTreeHelper(postorder, inorderRootIndex + 1, inorderEnd);
root.left = buildTreeHelper(postorder, inorderStart, inorderRootIndex - 1);
return root;
}
public static void main(String[] args) {
int[] inorder = {9, 3, 15, 20, 7}; // 左根右
int[] postorder = {9, 15, 7, 20, 3}; // 左右根
BinaryTreeBuilder builder = new BinaryTreeBuilder();
TreeNode root = builder.buildTree(inorder, postorder);
// 輸出樹的結構
printTree(root);
}
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
// 輔助方法:輸出樹的前序遍歷結果
private static void printTree(TreeNode node) {
if (node != null) {
System.out.print(node.val + " ");
printTree(node.left);
printTree(node.right);
}
}
3、結果輸出
3 9 20 15 7