二叉树的两种创建方式

在写之前,首先明确一点:
如 果 说 只 有 前 后 序 遍 历 那 么 是 不 能 够 创 建 二 叉 树 的 , 必 须 有 中 \color{red}{如果说只有前后序遍历那么是不能够创建二叉树的,必须有中}
序 遍 历 才 能 创 建 二 叉 树 \color{red}{序遍历才能创建二叉树}

第一种:根据前序和中序遍历构建二叉树

题目来源:
从前序与中序遍历序列构造二叉树

不论那种方法构造二叉树,我们的总体思路基本是相同的,但是就是在细节方法会有一点点不同。
我们都知道,前序遍历的的顺序是:

[根节点] [左子树的前序遍历结果] [右子树的前序遍历结果]

而中序遍历的结果是:

[左子树的中序遍历结果] [根节点] [右子树的中序遍历结果]

那么我们就需要在中序遍历中找出根节点,然后对左右子树的位置进行定位。这样一来,我们就知道了左子树和右子树的前序遍历和中序遍历结果,然后将其转接到左右子树的位置。接着对左右子树都是如此,不断递归。

那么具体的代码如下:

class Solution {
    //定义preorder的下标用来遍历前序数组
    int index;

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int n =preorder.length;
        return rebuildTree(preorder,inorder,0,n);
    }

    public TreeNode rebuildTree(int[] preorder,int[] inorder,int inleft,int inright){
        //设置临界条件
        if(index == preorder.length || inleft >= inright){
            return null;
        }
        //寻找中序遍历的根节点
        int pos = 0;
        while(pos < inright){
            if(inorder[pos] == preorder[index]){
                break;
            }
            pos++;
        }
        //设置根节点
        int rootvalue = preorder[index];
        index++;
        TreeNode root = new TreeNode(rootvalue);
        //设置左子树
        root.left = rebuildTree(preorder,inorder,inleft,pos);
        //设置右子树
        root.right = rebuildTree(preorder,inorder,pos+1,inright);
        return root;
    }

但是注意,这种方法缺点还是很明显的。

1.每一次的递归都要while寻找根节点一次,计算量增大
2.这种方法只能适用于没有重复值的数组

为了解决上述的第一个问题,那么我们可以用哈希映射来解决,但是第二个问题,目前笔者没有很好的思路。

第二种:根据中序和后序遍历构建二叉树

题目来源:

中序遍历的顺序:

[左子树的中序遍历] [根节点] [右子树的中序遍历]

后序遍历的顺序:

[左子树的后序遍历] [根节点] [右子树的中序遍历]

注意这种构建二叉树的思想其实和上面是一样的,但是细节处稍微有点不同,后序遍历的最后一位才是根节点,所有我们从后往前遍历,这就意味着我们需要先构建右子树然后再构建左子树。具体代码如下:

class Solution {
    int index;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        index = postorder.length - 1;
        return rebuildTree(inorder,postorder,0,inorder.length - 1);
    }

    public TreeNode rebuildTree(int[] inorder, int[] postorder,int inleft,int inright){
    	//设置临界条件
        if(index < 0 || inleft > inright){
            return null;
        }
        //寻找根节点
        int pos = inleft;
        while(pos <= inright){
            if(inorder[pos] == postorder[index]){
                break;
            }
            pos++;
        }
        //设置根节点
        int rootVal = postorder[index];
        TreeNode root = new TreeNode(rootVal);
        index--;
        //设置右子树
        root.right = rebuildTree(inorder,postorder,pos + 1,inright);
        //设置左子树
        root.left = rebuildTree(inorder,postorder,inleft,pos-1);
        return root;
    }
}

同样,这种方式和上面的缺陷一样,如果改进的话需要用哈希映射来进行查找,而且如果数组有重复元素就会出错。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值