剑指Offer-重建二叉树

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

解题思路:
假如已知先序序列为ABDECF,中序序列为DBEAFC,如何求解后序序列?由于先序遍历树的规则为根左右,因此可以得出先序序列的第一个元素一定为根节点,即A就是根节点。再看中序序列规则为左根右,再根据结点A的位置,可判断在中序序列中,A的左边的元素即DBE为左子树包含的元素,A的右边的元素FC为右子树中的元素。

其次,递归求解左子树(左子树先序为BDE,中序为DBE),递归求解右子树(右子树先序为CF ,中序为FC)。如此递归到没有左右子树为止。

总结解题步骤:
1.确定树的根节点。树根是当前树中所有元素在先序遍历中最先出现的元素,即先序遍历的第一个结点即为根节点。
2.求解树的子树。找到根在中序遍历序列中的位置。位置左边的结点为左子树,位置右边的结点为右子树。如果根节点的左边或者右边为空,那么该方向子树为空;如果根节点边和右边都为空,那么根节点已经为叶子结点。
3.对二叉树的左右孩子分别进行步骤1、2,直至求出整个二叉树结构位置。

具体实现代码:

	  public TreeNode buildTree(int[] preorder, int[] inorder) {
		  TreeNode root = reBuild(preorder,inorder,0,preorder.length - 1,0,inorder.length -1 );
		  return root;
	  }
    
	  public TreeNode reBuild(int[] preorder,int[] inorder,int preStart,int preEnd,
			  int inStart,int inEnd) {
		  
		  if(preStart > preEnd || inStart > inEnd) {
			  return null;
		  }
		  int rootData = preorder[preStart];
		  TreeNode root = new TreeNode(rootData);
		  int index = findIndex(inorder,inStart,inEnd,rootData);
		  //左子树结点个数
		  int leftNum = index - inStart;
		  root.left = reBuild(preorder, inorder, preStart+1, preStart+leftNum, inStart, index - 1);
		  root.right = reBuild(preorder, inorder, preStart+1+leftNum, preEnd, index+1, inEnd);
		  return root;
	  }


	public  int findIndex(int[] inorder,int inStart,int inEnd,int rootData) {
		for(int i = inStart;i <= inEnd;i++) {
			if(inorder[i] == rootData) {
				return i;
			}
		}
		return -1;
	}

由中序遍历和后序遍历,重建二叉树类似于上例,直接上代码:

    	 	public TreeNode buildTree(int[] inorder, int[] postorder) {
	        return reBuild(inorder,postorder,0,inorder.length - 1,0,postorder.length - 1);
	    }

		public  TreeNode reBuild(int[] inorder, int[] postorder, int inStart,
				int inEnd, int postStart, int postEnd) {
			
			if(inStart > inEnd || postStart > postEnd) {
				return null;
			}
			int rootData = postorder[postEnd];
			//根节点
			TreeNode root = new TreeNode(rootData);
			
			//获取根节点在中序遍历中的位置
			int index = findIndex(inorder,inStart,inEnd,rootData);
			int leftNum = index - inStart;
			root.left = reBuild(inorder, postorder, inStart, index-1, postStart, postStart+leftNum-1);
			root.right = reBuild(inorder, postorder, index+1, inEnd, postStart+leftNum, postEnd -1 );
			return root;
		}
	 	
	 	public int findIndex(int[] inorder,int inStart,int inEnd,int rootData) {
	 		for(int i = inStart;i<= inEnd;i++) {
	 			if(rootData == inorder[i]) {
	 				return i;
	 			}
	 		}
	 		return -1;
	 	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值