根据先序和中序构造二叉树

 Construct Binary Tree from Preorder and Inorder Traversal

问题:

Given preorder and inorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

解决:

【解析】对于下面的这棵树:

红色是根节点,蓝色为左子树,绿色为右子树。

可以发现的规律是:
1. 先序遍历的从左数第一个为整棵树的根节点。
2. 中序遍历中根节点是左子树右子树的分割点

① 给定先序遍历结果和中序遍历结果,构造一棵二叉树。采用递归的方式解决该问题:
    a) 通过先序遍历找到第一个点作为根节点,在中序遍历中找到根节点并记录index;
    b) 因为中序遍历中根节点左边为左子树,所以可以记录左子树的长度并在先序遍历中依据这个长度找到左子树的区间,用同样方法可以找到右子树的区间。
    c) 递归的建立好左子树和右子树就好。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution { //18ms
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        int preLen = preorder.length;
        int inLen = inorder.length;
        return buildTree(preorder,0,preLen - 1,inorder,0,inLen - 1);
    }
    public TreeNode buildTree(int[] preorder,int preStart,int preEnd,int[] inorder,int inStart,int inEnd){
        if(preStart > preEnd || inStart > inEnd){
            return null;
        }
        int rootVal = preorder[preStart];
        int rootIndex = 0;
        for (int i = inStart;i <= inEnd ;i ++ ) {
            if(inorder[i] == rootVal){
                rootIndex = i;
                break;
            }
        }
        int llen = rootIndex - inStart;
        TreeNode root = new TreeNode(rootVal);
        root.left = buildTree(preorder,preStart + 1,preStart + llen,inorder,inStart,rootIndex - 1);
        root.right = buildTree(preorder,preStart + llen + 1,preEnd,inorder,rootIndex + 1,inEnd);

        return root; 
    }
}

② 在discuss中看到的,从两边向中间查找。

class Solution { //1ms
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTree(preorder,0,inorder,0,inorder.length - 1);
    }
    public TreeNode buildTree(int[] preorder,int preStart,int[] inorder,int inStart,int inEnd){
        if(inStart > inEnd){
            return null;
        }
        TreeNode root = new TreeNode(preorder[preStart]);
        int rootIndex = -1;
        for (int k = inStart,l = inEnd;k <= l ;k ++,l -- ) {//从两边向中间查找根节点
            if(inorder[k] == root.val) {
                rootIndex = k;
                break;
            } else if(inorder[l] == root.val) {
                rootIndex = l;
                break;
            }
        }
        root.left = buildTree(preorder,preStart + 1,inorder,inStart,rootIndex - 1);
        root.right = buildTree(preorder,preStart + rootIndex - inStart + 1,inorder,rootIndex + 1,inEnd);

        return root;
    }
}

转载于:https://my.oschina.net/liyurong/blog/1539493

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值