https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
这个题目因为区间的问题把我给整麻了。
根据解析,需要假定区间是左闭右开即[x, y)
所以,对于右区间里面y这个值不好处理,需要考虑指针越界的问题。
// 传入参数:两个数组,两对指针用来圈定两个遍历数组里面的范围
// 返回:整个树
// 内部逻辑:
// 终止条件:如果inorder数组len为0,则返回null,如果len为1,返回这个节点的值
// 如果len>1,那postorder的len也>1
// 所以开始继续划分:
// 1.找到中间节点的值,在中序遍历这里划分
// 2.middle作为中间节点root
// 3.中序划分了[leftInorder, rightInorder) 后序划分[leftPostorder, rightPostorder)作为左子树返回
// 4.中序划分了[leftInorder, rightInorder) 后序划分[leftPostorder, rightPostorder)作为右子树返回
// 如何更新四个指针的值?
// 开始定义:left都在最左边,right在最右边
// 左子树的定义:
// leftInorder = leftInorder, rightInorder = middle,
// leftPostorder不用更新
// rightPostorder = leftPostorder + ( middle - leftInorder )
// 右子树的定义:
// leftpostorder = 左子树的rightpostorder
// rightpostorder = 最后一个 - 1
// leftInorder = middle + 1, rightInorder = rightpostorder - leftpostorder
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
int leftInorder = 0;
int rightInorder = inorder.length;
int leftPostorder = 0;
int rightPostorder = rightInorder;
return traverse(inorder, postorder, leftInorder, rightInorder, leftPostorder, rightPostorder);
}
public TreeNode traverse(int[] inorder, int[] postorder, int leftInorder, int rightInorder, int leftPostorder, int rightPostorder){
//没有数组元素了
if(rightInorder - leftInorder < 1) return null;
//只有一个元素,叶子
if(rightInorder - leftInorder == 1){
System.out.println("只剩一个元素,返回:"+inorder[leftInorder]);
return new TreeNode(postorder[rightPostorder - 1]);
}
//大于一个元素
TreeNode root = new TreeNode(postorder[rightPostorder - 1]);
int lastone = rightPostorder;
//寻找中间节点
int middle;
for(middle = 0; middle < inorder.length; middle++){
if(postorder[lastone - 1] == inorder[middle]) break;
}
//leftInorder不用更新
rightInorder = middle;
//leftPostorder不用更新
rightPostorder = leftPostorder + rightInorder - leftInorder;
root.left = traverse(inorder, postorder, leftInorder,rightInorder, leftPostorder, rightPostorder);
leftPostorder = rightPostorder;
rightPostorder = lastone - 1;
leftInorder = middle + 1;
rightInorder = leftInorder + rightPostorder - leftPostorder;
root.right = traverse(inorder, postorder, leftInorder,rightInorder, leftPostorder, rightPostorder);
return root;
}
}
调通了第一题之后第二题就很快了,总算是把这两道题目给搞定了额。
// 解题方法:利用前序的中左右,可以知道最前面这个是根节点
// 在中序中找出来即可
// 1. 终止条件: if(size == 0) 空节点,返回 null
// if(size == 1)叶子节点,返回叶子值
// 2. 处理遍历逻辑:
// 定位middle;
// 中序左区间:
// leftinorder不用更换
// rightinorder = middle;
// 前序左区间:
// leftpreorder = leftpreorder + 1;
// rightpreorder = leftpreorder + rightinorder - leftinorder;
// root.left = traverse(前序左区间, 中序左区间);
// 中序右区间:
// leftinorder = middle + 1;
// rightinorder = lastone;
// 前序右区间:
// leftpreorder = rightpreorder;
// rightpreorder = leftpreorder + rightinorder - leftinorder;
// root.right = traverse(前序右区间, 中序右区间);
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
int leftinorder = 0;
int rightinorder = inorder.length;
int leftpreorder = 0;
int rightpreorder = rightinorder;
return traverse(preorder, inorder, leftpreorder, rightpreorder, leftinorder, rightinorder);
}
public TreeNode traverse(int[] preorder, int[] inorder, int leftpreorder, int rightpreorder, int leftinorder, int rightinorder){
if(rightinorder - leftinorder == 0) return null;
TreeNode root = new TreeNode(preorder[leftpreorder]);
if(rightinorder - leftinorder == 1) return root;
//保存右指针位置
int lastone = rightinorder;
//定位根节点
int middle;
for(middle = 0; middle < inorder.length; middle++){
if(preorder[leftpreorder] == inorder[middle]) break;
}
//中序左区间
rightinorder = middle;
rightpreorder = leftpreorder + rightinorder - leftinorder;
//前序左区间
leftpreorder = leftpreorder + 1;
rightpreorder = leftpreorder + rightinorder - leftinorder;
root.left = traverse(preorder, inorder, leftpreorder, rightpreorder, leftinorder, rightinorder);
// 中序右区间:
leftinorder = middle + 1;
rightinorder = lastone;
// 前序右区间:
leftpreorder = rightpreorder;
rightpreorder = leftpreorder + rightinorder - leftinorder;
root.right = traverse(preorder, inorder, leftpreorder, rightpreorder, leftinorder, rightinorder);
return root;
}
}