算法07(重建二叉树)

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出:

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

以下是用递归写出的方法,使用了时间换空间的做法,因为无法动态加载数组。

package Mypage;

public class Solution {
    
	public static void main(String[] args) {
		int[] pd = {3,4,9,7,6,5,8};
		int[] id = {9,4,7,3,5,6,8};
		Solution solution = new Solution();
		TreeNode tree = solution.buildTree(pd, id);
		print_tree(tree);
	}
	
	public TreeNode buildTree(int[] preorder, int[] inorder) {
		if(preorder.length==0){
			return null;
		}
		int root = preorder[0];//根节点
		int left_len = 0;//左子树个数
		int right_len = 0;//右子树个数
		
		for(int i = 0;i<inorder.length;i++){//循环遍历中序数组,找到左子树和右子树
			if(inorder[i]==root){//若遍历到根节点,则记录左子树的节点个数
				left_len = i;
				right_len = inorder.length-i-1;
			}
		}
		int[] pd_left = new int[left_len];//左子树前序
		int[] id_left = new int[left_len];//左子树中序
		int[] pd_right = new int[right_len];//右子树前序
		int[] id_right = new int[right_len];//右子树中序
//		System.out.println("=========前序============");
		for(int i = 1,j=0,k=0;i<preorder.length;i++){
			if(i<=left_len){
				pd_left[j++] = preorder[i];
//				System.out.println(preorder[i]);
			}else{
				pd_right[k++] = preorder[i];
//				System.out.println(preorder[i]);
			}
		}
//		System.out.println("=========中序============");
		for(int i = 0,j=0,k=0;i<inorder.length;i++){
			if(i<left_len){
				id_left[j++] = inorder[i];
//				System.out.println(inorder[i]);
			}else if((left_len)==i){
				continue;
			}else{
				id_right[k++] = inorder[i];
//				System.out.println(inorder[i]);
			}
		}
		Solution solution = new Solution();
		TreeNode rootNode = new TreeNode(root);
		//先递归左子树
		if(left_len!=0){//如果左子树不为空,则需要递归,递归返回的是左子树
			TreeNode leftNode = solution.buildTree(pd_left, id_left);//返回本节点的左子树
			//将左子树添加在根节点上
			rootNode.left = leftNode;
		}
		if(right_len!=0){//如果右子树不为空,则需要递归,递归返回的是右子树
			TreeNode rightNode = solution.buildTree(pd_right, id_right);//返回本节点的右子树
			//将左子树添加在根节点上
			rootNode.right = rightNode;
		}
		return rootNode;
    }
	
	public static void print_tree(TreeNode treeNode) {
		System.out.println(treeNode.val);
		if(treeNode.left != null){
			print_tree(treeNode.left);
		}
		if(treeNode.right != null){
			print_tree(treeNode.right);
		}
	}
}

思路解读:

  • 按照前序的特点,数组中的第一个数必定是根节点。
  • 按照中序特点,数组中根节点的左边必定是左子树,右边必定是右子树。、
  • 可以根据递归的方法遍历每个节点。

代码解读:

  1. 判断数组是否为空,为空则返回null。(第一次提交,就遇到这个坑,往后需要注意)
    在这里插入图片描述
  2. 遍历循环前序和中序,记录左子树和右子树的节点个数。
  3. 根据节点个数创建数组,获取到左子树前序中序和右子树前序中序。
  4. 创建当前节点,将当前节点的值传入。(当前节点的值就是前序第一个值)
  5. 开始递归,先递归左子树,将左子树返回值添加到当前节点的左子树上。之后递归右子树。
  6. 最后返回本节点。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值