java 重建二叉树_7. 重建二叉树(剑指 Offer 题解Java版)

本文转载自【微信公众号:五角钱的程序员,ID:xianglin965】经微信公众号授权转载,如需转载与原文作者联系

文章目录

7. 重建二叉树题目链接题目描述解题思路

7. 重建二叉树

题目链接

牛客网

https://www.nowcoder.com/practice/8a19cbe657394eeaac2f6ea9b0f6fcf6?tpId=13&tqId=11157&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking&from=cyc_github

题目描述

根据二叉树的前序遍历和中序遍历的结果,重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

a350cfbd9f1e5b29b69c3ef3e0444bf4.png

解题思路

前序遍历序列的第一个元素 3 就是二叉树的根节点,中序遍历序列的根节点 3 把这个序列分成两半部分,分别是[9]和[20,15,7],左半分部是根节点的左子树,右半分布是根节点的右,树。,

基于这个特点,我们可以采用递归的方法来做,其大致逻辑如下。

1、通过前序序列第一个元素确定根节点(例如 3)。

2、通过根节点把中序序列分成两个序列,一个是左子树序列([9]),一个是右子树序列([15,20,7)。

3、通过左右子树的中序序列可以求出前序遍历的左右子树序列(左:[9],右:[20,15,7])。

4、左右子树的前序序列第一个元素分别是根节点的左右儿子。

5、通过递归重复以上步骤(看代码吧,看了代码可能就好理解点了)。

前序遍历的第一个值为根节点的值,使用这个值将中序遍历结果分成两部分,左部分为树的左子树中序遍历结果,右部分为树的右子树中序遍历的结果。然后分别对左右子树递归地求解。

8c31f29d5872f12bc1ac20241f0592fb.png

package 重建二叉树;

/*

作者 :XiangLin

文件 :ReConstructBinaryTree.java

IDE :IntelliJ IDEA

*/

public class ReConstructBinaryTree {

public class TreeNode {

public int val;

public TreeNode left;

public TreeNode right;

public TreeNode(int val) {

this.val = val;

}

@Override

public String toString() {

return "TreeNode{" +

"val=" + val +

", left=" + left +

", right=" + right +

'}';

}

}

// // 缓存中序遍历数组每个值对应的索引

// private Map indexForInOrders = new HashMap<>();

public TreeNode reConstructBinaryTree(int[] pre, int[] in) {

if (pre == null || in == null) { //如果前序或者中序有一个是空直接返回

return null;

}

TreeNode root;

root = rebuildTree(pre, 0, pre.length - 1, in, 0, in.length - 1);

return root;

}

/**

*

* @param pre 前序列表

* @param preStart 前序序列的起位置

* @param preEnd 前序序列的起位置

* @param in 中序列表

* @param inStart 中序序列的起位置

* @param inend 中序序列的起位置

* @return

*/

// preStart-preEnd表示前序序列的起始位置,inStart-inEnd也一样表示中序序列的起始位置

private TreeNode rebuildTree(int[] pre, int preStart, int preEnd, int[] in, int inStart, int inend) {

if (preStart > preEnd | inStart > inend) { //停止递归的条件

return null;

}

//根节点

TreeNode root = new TreeNode(pre[preStart]);

// 寻找根节点在中序序列的位置

for (int i = inStart; i <= inend; i++) {

if (in[i] == pre[preStart]) {

// 可以计算出中序序列的左右子树序列为:左:inStart~i -1,右:i+1~inEnd。

// 前序序列的左右子树:左:preStart+1~preStart+i-inStart,右:preStart+i-inStart+1~preEnd

root.left = rebuildTree(pre, preStart + 1, preStart + i - inStart, in, inStart, i - 1);

root.right = rebuildTree(pre, preStart + i - inStart + 1, preEnd, in, i + 1, inend);

}

}

return root;

}

public static void main(String[] args) {

ReConstructBinaryTree r = new ReConstructBinaryTree();

int preorder[] = {3,9,20,15,7};

int inorder[] = {9,3,15,20,7};

TreeNode treeNode =r.reConstructBinaryTree(preorder, inorder);

System.out.println(treeNode);

}

}

输出:

TreeNode{val=3, left=TreeNode{val=9, left=null, right=null}, right=TreeNode{val=20, left=TreeNode{val=15, left=null, right=null}, right=TreeNode{val=7, left=null, right=null}}}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值