剑指offer-重建二叉树

本文详细解析了如何通过前序和中序遍历结果重建二叉树的算法,介绍了算法的基本原理,提供了完整的代码实现,并通过多个测试用例验证了算法的正确性和鲁棒性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:输入某二叉树的前序和中序遍历结果,请重建该二叉树

如二叉树

剑指offer-重建二叉树

 

前序遍历为 1,2,4,7,3,5,6,8

中序遍历为 4,7,2,1,5,3,8,6

前序遍历的特点:先遍历根节点,然后遍历左孩子节点,然后遍历右孩子节点。

中序遍历的特点:先遍历左孩子节点,然后遍历根节点,最后遍历右孩子节点。


解题过程

前序遍历先遍历根节点,可以获取根节点的值,循环找到中序遍历的根节点的位置,那么中序遍历数组的根节点左边的节点即为左孩子节点,右边的节点即为右孩子节点。

然后寻找左孩子节点的树结构,右孩子的树结构。直到只有一个元素

int[] preTraversal, int[] inTraversal, int preStart, int preEnd, int inStart, int inEnd
前序遍历数组 ,中序遍历数组,前序遍历开始,前序遍历结束 中序遍历开始 中序遍历结束

以示例二叉树为例,从前序遍历获取根节点的值,对比中序遍历根节点位置,

如题 rootValue=1, rootIndex=3

剑指offer-重建二叉树

 

前序遍历的左孩子节点对应的下标为 [1,2,3], 右孩子节点[4,5,6,7]

中序遍历的左孩子节点对应的下标[0,1,2],右孩子[4,5,6,7]

第二轮:遍历1的左孩子节点(关注有颜色的值)rootValue=2,rootIndex=2

剑指offer-重建二叉树

 

前序遍历的左孩子节点对应的下标为[2,3],右孩子节点 无

中序遍历的左孩子节点对应的下标[0,1],右孩子无

第三轮:遍历2的左孩子节点 rootValue=4,rootIndex=0

剑指offer-重建二叉树

 

前序遍历的左孩子节点对应的下标为无,右孩子节点 3

中序遍历的左孩子节点对应的下标无,右孩子无1

第四轮:遍历4的右孩子节点 rootValue7,rootIndex=1

剑指offer-重建二叉树

 

只有一个节点返回.

代码

/**
 * 中序 4,7,2,1,5,3,8,6 调用
 */
 public void reBuildBinaryTree(int[] preTraversal, int[] inTraversal) throws Exception {
     if (preTraversal == null || inTraversal == null || preTraversal.length == 0
     || inTraversal.length == 0 || preTraversal.length != inTraversal.length) {
         return;
     }
     TreeNode tree = buildBinaryTree(preTraversal, inTraversal, 0,
     preTraversal.length - 1, 0, preTraversal.length - 1);
     prePrintTree(tree);
     System.out.println();
     inPrintTree(tree);
     System.out.println();
}

//构建核心

public TreeNode buildBinaryTree(int[] preTraversal, int[] inTraversal, int preStart, int preEnd, int inStart, int inEnd) throws Exception {
 if (preStart > preEnd || inStart > inEnd) {
     return null;
 }
 int value = preTraversal[preStart];
 TreeNode tree = new TreeNode(value);
 int rootIndex = inStart;
 // 在中序遍历中获取根节点位置
 while (rootIndex <= inEnd && value != inTraversal[rootIndex]) {
     rootIndex++;
 }
 // 寻找根节点的左子节点
 if (rootIndex <= inEnd) {
     tree.left = buildBinaryTree(preTraversal, inTraversal, preStart + 1, preStart + rootIndex - inStart, inStart, rootIndex - 1);
 // 寻找根节点的右子节点
     tree.right = buildBinaryTree(preTraversal, inTraversal, preStart + rootIndex - inStart + 1, preEnd, rootIndex + 1, inEnd);
 }
 return tree;
}

前序中序输出

// 前序输出
 public void prePrintTree(TreeNode tree) {
     if (tree == null) {
         return;
     }
     System.out.print(tree.value + " ");
     prePrintTree(tree.left);
     prePrintTree(tree.right);
 }
 //中序输出
 public void inPrintTree(TreeNode tree) {
     if (tree == null) {
         return;
     }
     inPrintTree(tree.left);
     System.out.print(tree.value + " ");
     inPrintTree(tree.right);
 }

测试用例

// main函数测试用例
 public static void main(String[] args) throws Exception {
     int[] prearr = new int[]{1, 2, 4, 7, 3, 5, 6, 8};
     int[] inarr = new int[]{4, 7, 2, 1, 5, 3, 8, 6};
     int[] prearr1 = new int[]{1, 2, 3, 4, 5};
     int[] inarr1 = new int[]{5, 4, 3, 2, 1};
     int[] prearr2 = new int[]{1, 2, 3, 4, 5};
     int[] inarr2 = new int[]{1, 2, 3, 4, 5};
     // 异常测试
     int[] prearr3 = new int[]{1, 2, 3, 4, 5};
     int[] inarr3 = new int[]{5, 4, 3, 2, 6};
     BinaryTree binaryTree = new BinaryTree();
     binaryTree.reBuildBinaryTree(prearr, inarr);
     binaryTree.reBuildBinaryTree(prearr1, inarr1);
     binaryTree.reBuildBinaryTree(prearr2, inarr2);
     // 异常测试
     binaryTree.reBuildBinaryTree(prearr3, inarr3);
 }

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值