106.从中序与后序遍历序列构造二叉树
根据一棵树的中序遍历与后序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:
难度还好,递归法。终止条件是 两个数组的长度都为 0 时,返回 null 。后序遍历 左 右 根 。每次构造后序遍历时,后序数组的最后一个总是根结点,再根据这个根结点,还有题目规定 无重复元素,则在中序数组中找到当前根结点,以它为界限把中序数组分成左子树的中序数组和右子树的中序数组。而中序数组中 根结点 的位置,刚好放到后序数组中,该位置往前 是 左子树的后序遍历,该位置包括该位置往后 直到 倒数第二个元素 是右子树的后序遍历,最后一个为根结点。
再以此左子树的先、后数组 和 右子树的先、后数组做递归即可。
package com.programmercarl.tree;
/**
* @ClassName BuildTree
* @Descriotion TODO
* @Author nitaotao
* @Date 2022/7/5 12:37
* @Version 1.0
* https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
* 106. 从中序与后序遍历序列构造二叉树
**/
public class BuildTree {
/**
* @param inorder 中序遍历 1 2
* @param postorder 后序遍历 2 1
* @return
*/
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (inorder.length == 0 && postorder.length == 0) {
return null;
}
//上个数组的长度是相等的,因为元素个数相同
//后序遍历的第一个元素为根结点
TreeNode root = new TreeNode(postorder[postorder.length - 1]);
//在中序遍历中找到根结点
int rootIndex = 0;
for (int i = 0; i < inorder.length; i++) {
if (root.val == inorder[i]) {
rootIndex = i;
}
}
//中序数组分成左子树和右子树
int[] leftIn = new int[rootIndex];
int[] rightIn = new int[inorder.length - rootIndex - 1];
for (int i = 0; i < inorder.length; i++) {
if (i < rootIndex) {
leftIn[i] = inorder[i];
} else if (i > rootIndex) {
rightIn[i-rootIndex-1] = inorder[i];
}
}
//后序遍历数组 前rootIndex位是左子树的,后rootIndex位是右子树
int[] leftPost = new int[rootIndex];
int[] rightPost = new int[inorder.length - rootIndex - 1];
//最后一位结点,已经作为根结点被构建了。
for (int i = 0; i < postorder.length - 1; i++) {
if (i < rootIndex) {
leftPost[i] = postorder[i];
} else {
rightPost[i - rootIndex] = postorder[i];
}
}
//构建左右子树
root.left = buildTree(leftIn, leftPost);
root.right = buildTree(rightIn, rightPost);
return root;
}
public static void main(String[] args) {
new BuildTree().buildTree(new int[]{1, 2}, new int[]{2, 1});
}
}