剑指offer面试题6 重构二叉树

1、根据前序和中序遍历重构二叉树

1.1 题目

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

1.2 题目分析

在二叉树的前序遍历序列中,第一个数字总是树的根结点的值。但在中序遍历序列中,根结点的值在序列的中间,左子树的结点的值位于根结点的值的右边,而右子树的结点的值位于根结点的值的右边。因此我们需要扫描中序遍历序列,找到根结点的值,也就区分出左右子树的大小、位置。

1.3 代码实现

import java.util.HashMap;

class TreeNode {
     int val;
     TreeNode left;
     TreeNode right;
     TreeNode(int x) { val = x; }
}
public class ReconstructTree {
    public static TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if(pre==null && in==null){
            return null;
        }
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < in.length; i++) {
            map.put(in[i], i);
        }
        return solve(pre,in,0,pre.length-1,0,in.length-1,map);
    }
    public static TreeNode solve(int[] pre,int[] in,int preL,int preR,int inL,int inR,HashMap<Integer, Integer> map){
        if(preL>preR||inL>inR){
            return null;
        }
        TreeNode head = new TreeNode(pre[preL]);
        int numl = map.get(pre[preL]);
        head.left = solve(pre, in, preL+1, preL+numl-inL, inL, numl-1,map);
        head.right = solve(pre, in, preL+numl-inL+1, preR, numl+1, inR,map);
        return head;
    }
    public static void main(String[] args) {
        int[] a = {1,2,4,7,3,5,6,8};
        int[] b = {4,7,2,1,5,3,8,6};
        TreeNode node = reConstructBinaryTree(a, b);
    }
}

2、根据中序和后序遍历重构二叉树

2.1 题目分析

中序和后序重构的过程与先序和中序的过程类似。先序和中序的过程是用先序数组最左的值来对中序数组进行划分,因为这里头节点的值。后序数组中头节点的值是后序数组最右的值,所以用后序最右的值来划分中序数组。

2.2 代码实现

//根据中序和后序数组重构二叉树
    public static TreeNode inPosToTree(int[] in,int[] pos){
        if(in==null || pos==null){
            return null;
        }
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < in.length; i++) {
            map.put(in[i], i);
        }
        return solve2(in, pos, 0, in.length-1, 0, pos.length-1,map);
    }
    public static TreeNode solve2(int[] in,int[] pos,int inL,int inR,int posL,int posR,HashMap<Integer, Integer> map){
        if(inL>inR||posL>posR){
            return null;
        }
        TreeNode node = new TreeNode(pos[posR]);
        int num = map.get(node.val);
        node.right = solve2(in, pos, num+1, inR, posR+num-inR, posR-1,map);
        node.left = solve2(in, pos, inL, num-1, posL, posR+num-1-inR, map);
        return node;
    }

3、通过先序和后序重构二叉树

3.1 题目

通过先序和后序重构二叉树,但大多数情况下并不能通过这两个数组把原来的树重构出来。这是因为很多结构不同的树中,先序与后序数组是一样的。

3.2 题目分析

然后需要分析出什么样的树可以被先序和后序数组重建,如果一棵二叉树除叶节点之外,其他所有的节点都有左孩子和右孩子,只有这样的树才可以被先序和后序数组重构出来。最后通过划分左右子树各自的先序与后序数组的方式重构整棵树。

3.3 代码实现

//根据前序和后序遍历重构二叉树
    public static TreeNode proPosToTree(int[] pro,int[] pos){
        if(pro==null || pos==null){
            return null;
        }
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < pos.length; i++) {
            map.put(pos[i], i);
        }
        return solve3(pro, pos, 0, pro.length-1, 0, pos.length-1, map);
    }
    public static TreeNode solve3(int[] pro,int[] pos,int proL,int proR,int posL,int posR,HashMap<Integer, Integer> map){
        TreeNode head = new TreeNode(pos[posR--]);
        if(proL==proR){
            return head;
        }
        int num = map.get(pro[++proL]);
        head.left = solve3(pro, pos, proL, proL+num-posL, posL, num, map);
        head.right = solve3(pro, pos, proL+num-posL+1, proR, num+1, posR, map);
        return head;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值