private int[] pre
private int[] post;
public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {
pre = preorder;
post = postorder;
return buildTree(0,0,pre.length);
}
private TreeNode buildTree(int i,int j,int n){
if (n==0) return null;
TreeNode root = new TreeNode(pre[i++]);
if (n==1) return root;
int L = 1;
for (;L<n;L++) if (post[j+L-1]==pre[i]) break;
root.left = buildTree(i,j,L);
root.right = buildTree(i+L,j+L,n-1-L);
return root;
}
思路:
首先要知道
前序遍历
[根节点,(左子树),(右子树)]
后序遍历
[(左子树),(右子树),根节点]
那么,我们可以知道根节点就是前序遍历中的首元素,那么怎么将左右子树划分开来呢?如果我们知道左子树的长度是不是就可以划分开左右子树了呢?那长度又怎么获取呢?
前序遍历中左子树的根节点会出现在后序遍历的左子树的哪里呢?
答案是:最后一个
即有:pre[1]==post[L-1]
设i为前序遍历左子树的首位元素索引,j为后序遍历左子树首位元素的索引,有pre[i]=post[j+L-1]
由此即可划分左右子树进行接下来的递归
- 将preorder和postorder存储到类中的成员变量,减少了传参时的繁琐
- 初始时,前序遍历左子树的首位元素索引是1,但是答案里传的是0,这是因为需要先创建根节点,创建之后i就会自增1,而后序遍历的左子树首位元素索引是0,也就是传了0,并且传了子树节点的长度
- 如果该子树长度为0,直接返回null,为1,则创建根节点后返回,长度大于1,继续划分左右子树
- 循环获取左子树长度后,继续递归创建左右子树
- 返回root