剑指offer+面试题7-二叉树-重建二叉树(java解答)

题目描述

输入某二叉树前序遍历和中序遍历的结果,重建该二叉树。

思路

二叉树的构建可以划分为构建左右子树两个小问题,大小问题本质一致,可以递归实现

  1. 根据前序遍历的第一个数字创建根结点
  2. 在中序遍历序列找到根结点的位置
  3. 确定左右子树节点数量
  • 时间复杂度:O(N)
  • 空间复杂度:O(1)

二叉树的定义及打印

重建二叉树的代码实现

public BinaryTreeNode Construct(int preorder[],int inorder[]) {
		if(preorder==null || inorder==null||preorder.length<=0||inorder.length<=0||preorder.length!=inorder.length)
			throw new RuntimeException("数组不符合规范!");
		return ConstructCore(preorder,0,preorder.length-1,
				inorder,0,inorder.length-1);
	}
	public BinaryTreeNode ConstructCore(int preorder[],int startPreorder,int endPreorder,
										int inorder[],int startInorder, int endInorder)
	{
		//停止递归的条件
		if(startPreorder>endPreorder||startInorder>endInorder)
            return null;
		
		BinaryTreeNode root=new BinaryTreeNode(preorder[startPreorder]);
		
		//前向序列和中序序列不匹配
		if(startPreorder==endPreorder && startInorder==endInorder) {
			if(preorder[startPreorder]!=inorder[startInorder])
				throw new RuntimeException("数组不符合规范!");
			return root;
		}
		
		for(int i=startInorder;i<=endInorder;i++)
		{
			if(preorder[startPreorder]==inorder[i]) {
				//其中(i-startInorder)为中序遍历左子树结点数
				//左子树
				root.m_pleft=ConstructCore(preorder,startPreorder+1,startPreorder+(i-startInorder),
						inorder,startInorder,i-1);
				//右子树
				root.m_pright=ConstructCore(preorder,startPreorder+(i-startInorder)+1,endPreorder,
						inorder,i+1,endInorder);
			}
		}
		return root;
	}

测试

  • 普通二叉树(完全二叉树,不完全二叉树)
  • 特殊二叉树(左斜树,右斜树)
  • 特殊输入测试(根结点为null;前序遍历与中序遍历不匹配)
	// ======== 测试代码 ========
	public void Test(String testName,int preorder[],int inorder[],int length) {
		if(testName!=null)
			System.out.println(testName+" begins");
		
		System.out.print("The preorder sequence is: ");
		for (int i=0;i<preorder.length;i++)
			System.out.print(preorder[i]+" ");
		System.out.println();
		
		System.out.print("The inorder sequence is: ");
		for (int i=0;i<inorder.length;i++)
			System.out.print(inorder[i]+" ");
		System.out.println();
		
	    BinaryTreeNode treeNode=Construct(preorder, inorder);
	    //T07_BinaryTree print=new T07_BinaryTree();
	    //print.printTree(treeNode);		
	}

	// ======== 普通二叉树 ========
	// 不完全二叉树
	//	              1
	//	           /     \
	//	          2       3  
	//	         /       / \
	//	        4       5   6
	//	         \         /
	//	          7       8
	public void Test1()
	{
		int length=8;
		int[] preorder = {1, 2, 4, 7, 3, 5, 6, 8};
	    int[] inorder = {4, 7, 2, 1, 5, 3, 8, 6};
	    Test("Test1",preorder,inorder,length);
	}
	
	// 完全二叉树
	//  	1
	//   /     \
	//  2       3  
	// / \     / \
	//4   5   6   7
	public void Test2()
	{
		int length=7;
		int[] preorder = {1, 2, 4, 5, 3, 6, 7};
	    int[] inorder = {4, 2, 5, 1, 6, 3, 7};
	    Test("Test2",preorder,inorder,length);
	}
	
	// ======== 特殊二叉树 ========
	// 所有结点都没有右子结点的二叉树
	//  	  1
	// 		 / 
	//		2   
	//	   / 
	//	  3 
	//	 /
	//	4
	// /
	//5
	public void Test3()
	{
		int length=5;
		int[] preorder = {1, 2, 3, 4, 5};
	    int[] inorder = {5, 4, 3, 2, 1};
	    Test("Test3",preorder,inorder,length);
	}
	
	// 所有结点都没有左子结点
	//  1
	//   \ 
	//    2   
	//     \ 
	//      3 
	//       \
	//        4
	//         \
	//          5
	public void Test4()
	{
		int length=5;
		int[] preorder = {1, 2, 3, 4, 5};
	    int[] inorder = {1, 2, 3, 4, 5};
	    Test("Test4",preorder,inorder,length);
	}
	
	// ======== 特殊输入测试 ========
	//输入空指针
	public void Test5()
	{
		int length=0;
		int[] preorder = {};
	    int[] inorder = {};
	    Test("Test5",preorder,inorder,length);
	}
	
	//输入的两个序列不匹配
	public void Test6()
	{
		int length=7;
		int[] preorder = {1, 2, 4, 5, 3, 6, 7};
	    int[] inorder = {4, 2, 8, 1, 6, 3, 7};
	    Test("Test6",preorder,inorder,length);
	}
	
	
	public static void main(String[] args) {
		T07_ConstructBinaryTree main=new T07_ConstructBinaryTree();
		main.Test1();
		//main.Test2();
		//main.Test3();
		//main.Test4();
		//main.Test5();
		//main.Test6();
		
	}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值