106. 从中序与后序遍历序列构造二叉树
难度中等
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
思路
需要明白的知识点有:
- 中序遍历中一个节点的左侧是它的左子树的所有节点,右侧是它的右子树的所有节点
- 后续遍历中的最后一个是当前节点,其左子树和右子树均在其左侧
我们可以根据后续遍历找到当前节点,然后找到当前根节点在中序数组中的位置,进而由根节点的位置及其子树的范围确定新的左子树与右子树的范围,然后进行不断递归,直到最后遍历完整个数组。
我们无法确定后续遍历中左子树与右子树的范围,但是可以从中序遍历中获得这个值
具体请看37与38行
package cn.edu.xjtu.carlWay.tree.postAndInConstructBinaryTree;
import cn.edu.xjtu.Util.TreeNode.TreeNode;
/**
* 106. 从中序与后序遍历序列构造二叉树
* 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
* <p>
* https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
*/
public class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
return helpBuild(inorder, 0, inorder.length, postorder, 0, postorder.length);
}
private TreeNode helpBuild(int[] inorder, int inLeft, int inRight, int[] postorder, int postLeft, int postRight) {
// 没有元素了
if (inRight - inLeft < 1) {
return null;
}
// 只有一个元素了
if (inRight - inLeft == 1) {
return new TreeNode(inorder[inLeft]);
}
// 后序数组中最后一个元素即为根节点
int rootVal = postorder[postRight - 1];
TreeNode root = new TreeNode(rootVal);
// 找到根节点在中序数组中的位置
int rootIndex = 0;
for (int i = inLeft; i < inRight; i++) {
if (inorder[i] == rootVal) {
rootIndex = i;
break;
}
}
root.left = helpBuild(inorder, inLeft, rootIndex, postorder, postLeft, postLeft + (rootIndex - inLeft));
root.right = helpBuild(inorder, rootIndex + 1, inRight, postorder, postLeft + (rootIndex - inLeft), postRight - 1);
return root;
}
}