总结
在二叉树任一节点都可以看成 根,左子树,右子树 三个部分,不管什么遍历方法,这三部分在遍历数组中的长度都是一样长的(这不是废话吗?)。
所以 分治 + 递归 就可以“轻松”的解决了。
代码实现上大概有三种方法:
- 递归传递 边界,长度
- 递归传递 两个新的数组
- 用map来记录坐标信息
105.从前序与后序遍历序列构造二叉树
总结
Sample & Demo Code
class Solution {
int[] preorder;
int[] inorder;
int pre_idx = 0;
HashMap<Integer, Integer> idx_map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
this.inorder = inorder;
int idx = 0;
for(int i : inorder)
idx_map.put(i, idx++);
return helper(0, idx);
}
private TreeNode helper(int left, int right) {
if(left >= right) return null;
int root_val = preorder[pre_idx];
TreeNode root = new TreeNode(root_val);
int index = idx_map.get(root_val);
pre_idx++;
root.left = helper(left, index);
root.right = helper(index+1, right);
return root;
}
}
Sample Code
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return build(preorder, inorder, 0, 0, inorder.length);
}
public TreeNode build(int[] preOrder, int[] inOrder, int preStart, int inStart, int length) {
if (length==0) return null;
int root_val = preOrder[preStart];
TreeNode treeNode = new TreeNode(root_val);
if (length== 1) return treeNode;
//必须从后开始遍历,不然会非常慢
for (int i = length-1; i >= 0; i--) {
if (root_val == inOrder[inStart+i]) {
treeNode.left = build(preOrder, inOrder, preStart+1, inStart, i);
treeNode.right = build(preOrder, inOrder, preStart+1+i, inStart+i+1, length-i-1);
return treeNode;
}
}
return null;
}
}
106. 从中序与后序遍历序列构造二叉树
总结
Sample & Demo Code
public class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
int inlen = inorder.length;
int polen = postorder.length;
if(inorder.length == 0) return null;
if(inorder.length == 1) return new TreeNode(inorder[0]);
int root_val = postorder[polen-1];
int point = 0;
for(int i = 0; i < inlen; i++) {
if(inorder[i] == root_val) {
point = i;
break;
}
}
TreeNode root = new TreeNode(root_val);
root.left = buildTree(Arrays.copyOfRange(inorder, 0, point), Arrays.copyOfRange(postorder, 0, point));
root.right = buildTree(Arrays.copyOfRange(inorder, point+1, inlen), Arrays.copyOfRange(postorder, point, polen-1));
return root;
}
}
Sample Code
在root.right = buildeTree(…);处的stop的值其实是中序表的同一层次的根节点
即如图为例,第一层递归是3,进入root的右子树的递归后,变成了20
同时需要注意,这种写法每次都会递归到叶子节点的两个null子节点后才会触发return条件
这种写法在写递归的root.left = … 和 root.right = … 的时候顺序不能颠倒,而其他方法在这里是可以颠倒的,因为这种写法公用了 in 和 post,并依赖于 in 和 post
class Solution {
private int in;
private int post;
public TreeNode buildTree(int[] inorder, int[] postorder) {
int n = inorder.length;
in = n - 1;
post = n - 1;
return buildTree(inorder, postorder, (long) Integer.MIN_VALUE - 1);
}
private TreeNode buildTree(int[] inorder, int[] postorder, long stop) {
System.out.println("stop:"+stop+", in:"+in+", post:"+post);
if (post < 0) return null;
if (inorder[in] == stop) {
in--;
return null;
}
int rootVal = postorder[post--];
TreeNode root = new TreeNode(rootVal);
root.right = buildTree(inorder, postorder, rootVal);
root.left = buildTree(inorder, postorder, stop);
return root;
}
}
>Input:
[9,3,15,20,7]
[9,15,7,20,3]
>Ouput:
in:4, post:4, stop:-2147483649
in:4, post:3, stop:3
in:4, post:2, stop:20
in:4, post:1, stop:7
in:3, post:1, stop:20
in:2, post:1, stop:3
in:2, post:0, stop:15
in:1, post:0, stop:3
in:0, post:0, stop:-2147483649
in:0, post:-1, stop:9
in:0, post:-1, stop:-2147483649
Sample Code
public class Solution {
private int[] postorder;
private Map<Integer, Integer> hash;
public TreeNode buildTree(int[] inorder, int[] postorder) {
int inLen = inorder.length;
int postLen = postorder.length;
this.postorder = postorder;
hash = new HashMap<>();
for (int i = 0; i < inLen; i++) {
hash.put(inorder[i], i);
}
return buildTree(0, inLen - 1, 0, postLen - 1);
}
private TreeNode buildTree(int inLeft, int inRight, int postLeft, int postRight) {
if (inLeft > inRight || postLeft > postRight)
return null;
int pivot = postorder[postRight];
int pivotIndex = hash.get(pivot);
TreeNode root = new TreeNode(pivot);
root.right = buildTree(pivotIndex + 1, inRight, postRight - inRight + pivotIndex, postRight - 1);
root.left = buildTree(inLeft, pivotIndex - 1, postLeft, postRight - inRight + pivotIndex - 1);
return root;
}
}
链接:
https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/solution/hou-xu-bian-li-python-dai-ma-java-dai-ma-by-liwe-2/