leetcode-中等题-106. 从中序与后序遍历序列构造二叉树,105. 从前序与中序遍历序列构造二叉树

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;       
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值