剑指offer题目记录04——重建二叉树

剑指offer题目记录04——重建二叉树

写在前面

  • 作者在写这道题目之前,已经大约有大半年的时间没有看“树”了,所以有同样情况的兄弟们,请先参考学习有关树与二叉树及其遍历的基本概念,再回到这篇文章中学习,这里将不再对树的概念和特性进行科普。

题目描述

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

思路

  • 先了解二叉树的三种遍历方式,前序遍历,中序遍历和后序遍历。
  • 题目中给出了前序遍历和中序遍历,前序遍历的特点:前序遍历结果中第一个元素是根节点,接下来的是左子树和右子树。中序遍历特点:先是左子树,然后是根节点,然后是右子树。
  • 我们可以通过前序遍历结果找到当前的“根”,也就是结果中的第一个元素,记为root。
  • 用root到中序遍历的结果中寻找相同元素,并返回该元素下标,记为index。
  • 由于中序遍历的结果为:先是左子树,然后根节点,最后是右子树。所以可以确定,index向左的部分,为root下的左子树,index向右的部分为index下的右子树。
  • 根据已经在中序遍历中分好的左右子树的长度,到前序遍历结果中,将前序遍历中的左右子树区分开。
  • 拥有了左子树的前序遍历结果和中序遍历结果,只需要将当前root的左子树赋值为递归程序的返回值,右子树同理。
  • 最后只要返回当前root即可,下面是大概的解释图,看不懂可以留言或者私聊我,给你讲懂:
    在这里插入图片描述

代码演示

这是节点类

class TreeNode {
        int value;
        TreeNode leftNode;
        TreeNode rightNode;

        public TreeNode(int value) {
            this.value = value;
        }
    }

这是具体的转换过程,一些细节写在注释中了

public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if (pre == null || in == null) {
            return null;
        }
        List<Integer> preList = new ArrayList<>(); // 因为给进来的参数是数组,我把他转化为list,方便处理
        List<Integer> inList = new ArrayList<>();
        for (int index = 0; index < pre.length; index++) {
            preList.add(pre[index]);
            inList.add(in[index]);
        }
        return ReTree(preList, inList);
    }

    private TreeNode ReTree(List<Integer> pre, List<Integer> in) { // 这个是真正的递归程序
        if (pre == null || in == null) {
            return null;
        }
        int rootValue = pre.get(0);  // 找到前序遍历结果中的第一个元素,也就是Root
        System.out.println("rootValue : " + rootValue);
        TreeNode root = new TreeNode(rootValue); // 建立根节点,并赋值

        int index = in.indexOf(rootValue); // 找到中序遍历中对应元素的下标
        if (index == 0) {      // 这里的两个if-else是为了确定元素是否存在左右子树
            // 左子树为null     // 如果不存在左右子树,参数为null
            root.leftNode = ReTree(null, null);
        } else {              // 这一步给左子树赋值
            root.leftNode = ReTree(pre.subList(1, index + 1), in.subList(0, index));
        }
        if (index + 1 == in.size()) {
            // 右子树为null
            root.rightNode = ReTree(null, null);
        } else {             // 这一步给右子树赋值
            root.rightNode = ReTree(pre.subList(index + 1, pre.size()), in.subList(index + 1, in.size()));
        }
        return root;        // 向上返回根节点作为结果
    }

这是输出树的代码(中序输出),很容易写,用作验证结果。

public void printTree(TreeNode root) {
        if (root == null) {
            return;
        }
        printTree(root.leftNode);
        System.out.println(root.value);
        printTree(root.rightNode);
    }

总结

  • 能看到这里的朋友,先谢谢你,你尊重原创,尊重知识。
  • 如果有什么疑问或者我的文章有些的不好或不准确的地方,欢迎留言或私信我!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值