前序+中序:
public TreeNode buildTree(int[] preorder, int[] inorder) {
return buildTree(preorder, inorder, 0, 0, inorder.length);
}
public TreeNode buildTree(int[] pre, int[] in, int preStart, int inStart, int length) {
if (length == 0) return null;
// inStart==inEnd 也要进行下面的步骤,防止pre 和 in 序列不匹配
// 构造以 pre[preStart] 为根节点的树
int j = 0; // 中序中找到根节点
while (j < length && in[j + inStart] != pre[preStart]) {
j++;
}
if (j >= length) {
throw new RuntimeException("前序中序不匹配");
}
TreeNode root = new TreeNode(pre[preStart]);
// 左子树的节点数 j , 右子树的节点数 length-j-1
// 中序中以 索引 j+inStart 划分成左右两部分,分别构造左右子树
root.left = buildTree(pre, in, preStart + 1, inStart, j);
root.right = buildTree(pre, in, preStart + j + 1, j + inStart + 1, length - j - 1);
return root;
}
中序+后序
public TreeNode buildTreeByInAndPost(int[] in, int[] post) {
if (in == null || post == null || in.length != post.length) {
throw new RuntimeException("中序和后序不匹配");
}
return buildTreeByInAndPost(in, post, 0, post.length - 1, post.length);
}
private TreeNode buildTreeByInAndPost(int[] in, int[] post, int inStart, int postEnd, int length) {
if (length == 0) return null;
int j = 0;
while (j < length && in[j + inStart] != post[postEnd]) {
j++;
}
if (j >= length) {
throw new RuntimeException("中序和后序不匹配");
}
// in[j] 等于 post[postEnd]
// 左子树的数目 j , 右子树 length-j-1
int rightSize = length - j - 1;
TreeNode root = new TreeNode(post[postEnd]);
root.left = buildTreeByInAndPost(in, post, inStart, postEnd - rightSize - 1, j); // 后序序列的前一部分是左子树节点
root.right = buildTreeByInAndPost(in, post, inStart + j + 1, postEnd - 1, rightSize); // 后序序列的后半部分是 右子树节点
return root;
}
前序+后序
构造出的二叉树不止一种,返回其中的一种即可
public TreeNode constructFromPrePost(int[] pre, int[] post) {
if (pre.length != post.length) {
throw new RuntimeException("前序和后序不匹配");
}
return buildTreeByPreAndPost(pre, post, 0, post.length - 1, pre.length);
}
public TreeNode buildTreeByPreAndPost(int[] pre, int[] post, int preStart, int postEnd, int length) {
if (length == 0) {
return null;
}
if (pre[preStart] != post[postEnd]) {
throw new RuntimeException("前序和后序不匹配");
}
if (length == 1) {
// 只有一个节点
return new TreeNode(post[postEnd]);
}
TreeNode root = new TreeNode(post[postEnd]);
int j = 1; // 跳过前序序列第一个元素(根节点)
while (j < length && pre[j + preStart] != post[postEnd - 1]) j++; //在前序序列中找到 等于后序序列的倒数第二个值(右子树的根节点)
if (j == length) {
throw new RuntimeException("前序和后序遍历");
}
int leftSize = j - 1;
int rightSize = length - 1 - leftSize;
root.left = buildTreeByPreAndPost(pre, post, preStart + 1, postEnd - rightSize - 1, leftSize);
root.right = buildTreeByPreAndPost(pre, post, preStart + 1 + leftSize, postEnd - 1, rightSize);
return root;
}