首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >重建二叉树(Java)

重建二叉树(Java)

作者头像
全栈程序员站长
发布于 2022-07-01 12:28:24
发布于 2022-07-01 12:28:24
29800
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

题目:

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
struct BinaryTreeNode{
	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
}

知识点:

树:除了根结点之外每个结点只有一个父结点,根结点没有父结点;除了叶结点之外所有结点都有一个或多个子结点,叶结点没有子结点。父结点和子结点之间用指针链接。

二叉树:二叉树是树的一种特殊结构,在二叉树中每个结点最多只能有两个子结点。在二叉树中最重要的操作是遍历,即按照某一顺序访问树中的所有结点。树的遍历方式:

前序遍历:先访问根节点,再访问左子结点,最后访问右子结点;(根左右)

中序遍历:先访问左子结点,再访问根结点,最后访问右子结点;(左根右)

后序遍历:先访问左子结点,再访问右子结点,最后访问根结点;(左右根)

前序遍历、中序遍历、后序遍历都可以用递归和循环进行实现。故树的遍历有3种方式6种实现。

宽度优先遍历:先访问树的第一层结点,再访问树的第二层结点……一直到访问到最下面的一层结点。在同一层结点中,以从左到右的顺序依次访问。

二叉搜索树:左子结点总是小于或等于根结点,而右子结点总是大于或等于根结点。(二叉搜索树的搜索时间可以平均在O(logn)的时间内)。

二叉树的特例是红黑树。堆分为最大堆和最小堆。在最大堆中根节点的值最大,在最小堆中根节点的值最小。红黑树是把树中的结点定义为红、黑两种颜色,并通过规则确保从根结点到叶结点的最长路径的长度不超过最短路径的两倍。

解题思路:

题目中给了我们先序遍历和中序遍历;在二叉树的前序遍历中,第一个数字总是树的根结点的值。但在中序遍历序列中,根结点的值在序列的中间,左子树的结点的值位于根结点的值的左边,而右子树的结点的值位于根结点的值的右边。因此我们需要扫描中序遍历序列,才能找到根结点的值。

题目给出的前序遍历序列的第一个数字1就是根结点的值。扫描中序遍历序列,就能确定根结点的值的位置。根据中序遍历的特点,在根结点的值1前面的3个数字都是左子树结点的值,位于1后面的数字都是右子树结点的值。

由于在中序遍历序列中,有3个数字是左子树结点的值,因此左子树总共有3个左子结点。同样,在前序遍历的序列中,根结点后面的3个数字就是3个左子树结点的值,再后面的所有数字都是右子树结点的值。这样就在前序和中序遍历的两个序列中,分别找到了左右子树对应的子序列。

我们已经分别找到了左右子树的前序和中序遍历,我们可以用同样的方法分别去构建左右子树,即递归实现。

定义二叉树结构:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class TreeNode {
        //数据域
	public int data; 
	//左指针域
	public TreeNode left;
	//右指针域
	public TreeNode right;
        //构造带有参数的构造方法
	public TreeNode(int data) {
		this.data = data;
	}
        //重写toString方法
	public String toString() {
		return "TreeNode [data=" + data + ", left=" + left + ", right=" + right
				+ "]";
	}
}

前序和中序重建二叉树的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public TreeNode rebuildBinaryTree(int preorder[], int inorder[]) {
	if (preorder == null || inorder == null) { //如果前序或者中序有一个是空直接返回
		return null;
	}
               // 定义构建二叉树的核心算法
	TreeNode root = rebuildBinaryTreeCore(preorder, 0, preorder.length - 1,
			inorder, 0, inorder.length - 1);
	return root;
}
// 构建二叉树的核心算法
public TreeNode rebuildBinaryTreeCore(int preorder[], int startPreorder,
		int endPreorder, int inorder[], int startInorder, int endInorder) {
	if (startPreorder > endPreorder || startInorder > endInorder) { //停止递归的条件
		return null;
	}
	TreeNode root = new TreeNode(preorder[startPreorder]);
	for (int i = startInorder; i <= endInorder; i++) {
		if (preorder[startPreorder] == inorder[i]) {
			// 其中(i - startInorder)为中序排序中左子树结点的个数
			//左子树
			root.left = rebuildBinaryTreeCore(preorder, startPreorder + 1,
					startPreorder + (i - startInorder), inorder,
					startInorder, i - 1);
			//右子树
			root.right = rebuildBinaryTreeCore(preorder, (i - startInorder)
					+ startPreorder + 1, endPreorder, inorder, i + 1,
					endInorder);

		}
	}
	return root;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
	4,7,3数量为3个即i-startInorder
 1    2 4 7        3 5 6 8
      4 7 2    1   5 3 8 6

             1
         2       3
      4        5   6
         7   8
*/

测试方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) {
	int preorder[] = {1, 2, 4, 7, 3, 5, 6, 8};
	int inorder[] = {4, 7, 2, 1, 5, 3, 8, 6};
	TreeNode treeNode = rebuildBinaryTree(preorder, inorder);
	System.out.println(treeNode);
}

举一反三:

类似的由中序和后序构建二叉树和有前序和中序构建二叉树的思想是类似的。重建二叉树可以有前序和中序推导出来,也可以由中序和后序推导出来。这里实现由中序和后序重建二叉树。

有中序和后序重建二叉树代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static TreeNode rebuildBinaryTree(int[] postorder, int[] inorder) {
	if (postorder == null || inorder == null) {
		return null;
	}
	TreeNode root = rebuildBinaryTreeCore(postorder, 0,
			postorder.length - 1, inorder, 0, inorder.length - 1);
	return root;
}

public static TreeNode rebuildBinaryTreeCore(int[] postorder,
		int startPostorder, int endPostorder, int[] inorder,
		int startInorder, int endInorder) {

	if (startPostorder > endPostorder || startInorder > endInorder) { // 终止递归的条件
		return null;
	}
	TreeNode root = new TreeNode(postorder[endPostorder]);
	for (int i = startInorder; i <= endInorder; i++) {
		if (inorder[i] == postorder[endPostorder]) {
			root.left = rebuildBinaryTreeCore(postorder, startPostorder,
					startPostorder - 1 + (i - startInorder), inorder,
					startInorder, i - 1);
			root.right = rebuildBinaryTreeCore(postorder, startPostorder
					+ (i - startInorder), endPostorder - 1, inorder, i + 1,
					endInorder);
		}
	}
	return root;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
 *  后序:2  4  3  1          6    7    5
 *  中序:1  2  3  4     5    6    7
 *             5     
 *       1           7
 *           3     6  
 *         2   4   
 */

测试:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) {
	int []inorder = {1, 2, 3, 4, 5, 6, 7};
	int []postorder = {2, 4, 3, 1, 6, 7, 5};
	TreeNode treeNode = rebuildBinaryTree(postorder, inorder);
	System.out.println(treeNode);
}

小思:

这道编程考查对二叉树的遍历的理解程度,只有掌握了二叉树的三种遍历,才可以推导出二叉树的结构;

这道题它的经典之处在于递归,在每次递归时它的经典是把一颗完整的二叉树,分成了左子树、根、右子树,再在每个左右子树中再分,即把大问题转化为局部小问题,最后解决问题。值得学习,递归精髓。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/130472.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
LeetCode 105 :重建二叉树(超容易理解的解法!!!)
题目链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
五分钟学算法
2021/03/10
2.2K0
《剑指offer》第六天:重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 {1,2,4,7,3,5,6,8} 和中序遍历序列 {4,7,2,1,5,3,8,6},则重建二叉树并返回。
程序员小浩
2020/08/10
3320
剑指Offer面试题:5.重建二叉树
  在二叉树的前序遍历序列中,第一个数字总是树的根结点的值。但在中序遍历序列中,根结点的值在序列的中间,左子树的结点的值位于根结点的值的左边,而右子树的结点的值位于根结点的值的右边。因此我们需要扫描中序遍历序列,才能找到根结点的值。
Edison Zhou
2018/08/20
5040
剑指Offer面试题:5.重建二叉树
LeetCode 106: 从中序与后序遍历序列构造二叉树
Given inorder and postorder traversal of a tree, construct the binary tree.
爱写bug
2020/02/26
3360
算法-重建二叉树
chaibubble
2018/01/02
5290
算法-重建二叉树
图解LeetCode——剑指 Offer 07. 重建二叉树
根据题目描述,我们需要通过题目给出的一棵树的前序遍历和中序遍历,来重建这棵二叉树。那么首先我们需要知道这两种遍历的方式是怎么样的:
爪哇缪斯
2023/05/10
2660
图解LeetCode——剑指 Offer 07. 重建二叉树
【初阶数据结构篇】深入浅出:链式结构二叉树(二叉链)的实现与递归奥秘(上篇)
BinaryTree · petrichor/2024-summer-c-language - 码云 - 开源中国 (gitee.com)
半截诗
2024/10/09
1550
【初阶数据结构篇】深入浅出:链式结构二叉树(二叉链)的实现与递归奥秘(上篇)
二叉树(前序、中序、后序遍历图片步骤详解)
ps: 所谓的前序、中序、后续,就是对根节点而言的,左右的遍历顺序不变,前序就是根节点最先遍历,然后左右;中序就是把根节点放在中间遍历;后序则是把根节点放在最后遍历。
全栈程序员站长
2022/06/28
5250
二叉树(前序、中序、后序遍历图片步骤详解)
剑指offer - 重建二叉树 - JavaScript
题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
心谭博客
2020/04/21
3760
数据结构之二叉树
二叉树的定义: 二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要
xiangzhihong
2018/02/01
6880
数据结构之二叉树
【数据结构】关于二叉树,你必须知道的遍历方法!!!
1. 在计算机编程中,对数组进行遍历是常见操作。例如用循环语句依次访问数组中的每一个元素,以便进行数据处理、统计等操作。比如计算一个整数数组中所有元素的和,就需要遍历这个数组,将每个元素的值依次相加。
用户11288949
2024/09/24
1680
【数据结构】关于二叉树,你必须知道的遍历方法!!!
剑指 offer|07. 重建二叉树
(前序)preorder = [3,9,20,15,7], (中序)inorder = [9,3,15,20,7]
孟君
2023/02/23
2190
剑指 offer|07. 重建二叉树
LeetCode——遍历序列构造二叉树
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。 示例 1:
有礼貌的灰绅士
2023/04/17
2740
LeetCode——遍历序列构造二叉树
LeetCode 105: 从前序与中序遍历序列构造二叉树
Given preorder and inorder traversal of a tree, construct the binary tree.
爱写bug
2020/02/26
4020
通过前序+中序和后序+中序来构建二叉树
首先我们要知道,三种不同遍历方式的过程。看下图很容易理解,并且不容易忘。 前序遍历:根 左 右 中序遍历:左 根 右 后序遍历:左 右 根
帅地
2019/12/24
2.5K0
中序+前序与中序+后序之重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 {1, 2, 4, 7, 3, 5, 6, 8} 和中序遍历序列 {4, 7, 2, 1, 5, 3, 8, 6},则重建出如下图所示的二叉树并返回它的头结点。
公众号guangcity
2019/11/23
9780
【二叉树进阶】leetcode&牛客 二叉树进阶面试题
所以,解这道题之前,我们可以先来分析一下,哪些情况需要省略空括号,哪些情况不能省略 那对照着图我们很容易得出,括号的处理应该是这样的:
YIN_尹
2024/01/23
1760
【二叉树进阶】leetcode&牛客 二叉树进阶面试题
剑指 Offer(C++版本)系列:剑指 Offer 07 重建二叉树
同步GitHub在此 ? https://github.com/TeFuirnever/GXL-Skill-Tree 剑指 Offer(C++版本)系列:总目录和一些提高效率的说明 剑指 Offer(
我是管小亮
2021/07/20
3000
【算法】重建二叉树并进行后序遍历的Java实现
在二叉树的问题中,给定二叉树的前序遍历(Preorder)和中序遍历(Inorder)序列,如何求得其后序遍历(Postorder)序列是一个经典的面试题。本文将详细介绍如何通过Java实现这一过程。
人不走空
2024/05/29
1710
LeetCode重建二叉树详解[通俗易懂]
做完第一步之后,我们会发现,我们目前只具体确定了哪一个是根节点,哪些结点分别属于左右子树。但是由于树的递归特性。属于左子树的结点仍然符合前序遍历,中序遍历特点的。所以我们就是需要对刚刚分离出来的两部分分别再次用上述的方法,确定根节点,确定哪些结点属于左子树,哪些结点属于右子树。一次类推,直到结束。这就是这道题的大致思路。
全栈程序员站长
2022/07/01
2750
LeetCode重建二叉树详解[通俗易懂]
推荐阅读
相关推荐
LeetCode 105 :重建二叉树(超容易理解的解法!!!)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档