Day20:剑指 Offer 07. 重建二叉树

题目

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

代码实现

分治算法

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    TreeNode head;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder.length == 0){
            return head;
        }
        head = new TreeNode(preorder[0]);
        helper(head,preorder,inorder,0,-1,inorder.length);
        return head;
    }

    /**
     * 找到当前节点的前序位置和中序位置,
     * 前序序列中: 前序位置的下一个为它的左节点,前序位置加上(当前节点位置在中序的位置inPosition-左边界left,即左子树的数量)+1为它的右节点
     * 如果当前节点没有左节点,
     * @param node
     * @param preorder
     * @param inorder
     * @param prePosition 当前节点在前序序列的位置
     * @param left 中序的左边界 左开右开
     * @param right 中序的右边界
     * @return
     */
    public void helper(TreeNode node,int[] preorder, int[] inorder,int prePosition,int left,int right){
        //找到当前节点在中序遍历中的位置
        int inPosition = left;
        for (int i = left + 1; i < right; i++) {
            if (inorder[i] == preorder[prePosition]){
                inPosition = i;
                break;
            }
        }
        //当前节点中序位置不是左边界+1,才有左孩子
        if(inPosition !=  left + 1) {
            //当前节点的左节点位置为前序位置+1
            int leftIndex = prePosition + 1;
            node.left = new TreeNode(preorder[leftIndex]);
            
            //将当前节点在中序遍历中的位置作为左子树的右边界
            helper(node.left, preorder, inorder, leftIndex, left, inPosition);
        }
        //当前节点中序位置不是右边界-1,才有右孩子
        if (inPosition != right -1){
            //当前节点的右节点位置为前序位置+左子树的数量
            int rightIndex = prePosition + (inPosition - left);
            node.right = new TreeNode(preorder[rightIndex]);
            
            //将当前节点在中序遍历中的位置作为右子树的左边界
 helper(node.right,preorder,inorder,rightIndex,inPosition,right);
        }
    }
}

分治算法2

K神代码:利用hashmap避免了使用for循环找到中序遍历对应点的高时间复杂度

class Solution {
    int[] preorder;
    HashMap<Integer, Integer> dic = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        this.preorder = preorder;
        for(int i = 0; i < inorder.length; i++)
            dic.put(inorder[i], i);
        return recur(0, 0, inorder.length - 1);
    }
    TreeNode recur(int root, int left, int right) {
        if(left > right) return null;                          // 递归终止
        TreeNode node = new TreeNode(preorder[root]);          // 建立根节点
        int i = dic.get(preorder[root]);                       // 划分根节点、左子树、右子树
        node.left = recur(root + 1, left, i - 1);              // 开启左子树递归
        node.right = recur(root + i - left + 1, i + 1, right); // 开启右子树递归
        return node;                                           // 回溯返回根节点
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值