刷算法题(4)——JZ4 重建二叉树_牛客

一、题目

题目描述

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

示例1

输入

复制

[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]

返回值

复制

{1,2,5,3,4,6,7}

法一:递归,JAVA,数组

思路:递归过程,通过前序数组找到二叉树的根结点,再通过中序数组分出二叉树的左右子树,重复该过程直到数组没有元素

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
//法一:递归,数组
public class Solution {
    public int[] copyOfrange(int []array,int from,int to)
    {
        int[] result=new int[to-from];
        for(int i=from,j=0;i<to;i++,j++)
            result[j]=array[i];
        return result;
    }
    
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if(pre.length==0||in.length==0) return null;
        TreeNode root=new TreeNode(pre[0]);
        
        for(int i=0;i<in.length;i++)
        {
            if(pre[0]==in[i])
            {
                //java自带函数Array.copyOfrange,需要包import java.util.Arrays;
                //root.left=reConstructBinaryTree(Array.copyOfrange(pre,1,i+1),Array.copyOfrange(in,0,i));
                //root.right=reConstructBinaryTree(Array.copyOfrange(pre,i+1,pre.length),Array.copyOfrange(in,i+1,in.length));
                
                //自己写的数组复制函数
                root.left=reConstructBinaryTree(copyOfrange(pre,1,i+1),copyOfrange(in,0,i));
                root.right=reConstructBinaryTree(copyOfrange(pre,i+1,pre.length),copyOfrange(in,i+1,in.length));
            }
        }
        return root;
    }
}

法二:递归,JAVA,List

//重建二叉树,法二:递归,List
public static TreeNode Tree(List<int> preTree,List <int>midTree)
{
	if(preTree==null||preTree.Count==0||midTree==null||midTree.Count==0)
		return null;
	
	int i=1;

	//根结点
	int rootTree=preTree[0];
	//移除根结点
	preTree.RemoveAt(0);
	
	//新建结点存储当前值,并指向左右子树
	TreeNode treeNode=new TreeNode(rootTree);
	
	//左右子树
	List<int> midLeft=null;
	List<int> tempMid=new AarrayList<int>();//中序遍历左右子树
	List<int> preLeft=null;
	List<int> tempPre=new AarrayList<int>();//前序遍历左右子树
	bool isTree=false;
	
	foreach(var item in midTree)
	{
		tempMid.Add(item);
		tempPre.Add(preTree[i++]);
		if(item==rootTree)
		{
			
			//确认是一棵二叉树
			isTree=true;
			//左子树的中序遍历
			midLeft=tempMid;
			//中序遍历移除根结点
			midTree.RemoveAt(item);
			//新建临时结点,存储右子树
			tempMid=new List<int>();
			//左子树的前序遍历
			preLeft=tempPre;
			tempPre=new List<int>();
		}	
	}
	if(!isTree)
	{
		Console.WriteLine("不是正确的数");
		return null;
	}
	List<int> midRight=tempMid;
	List<int> preRight=tempPre;
	
	//递归左右子树
	treeNode.left=Tree(preLeft,midLeft);
	treeNode.right=Tree(preRight,midRight);
		
		
}

 

二、二叉树操作

二叉树结构:

public class TreeNode
{
	public int val;
	public TreeNode left;
	public TreeNode right;
	TreeNode(int x)//构造函数
	{
		val=x;
	}
}

前序遍历:根结点,左子树,右子树

public static void PreNode(TreeNode node,List<int> treeList)
{
	if(node!=null)
	{
		treeList.Add(node.val);
		PreNode(node.left,treeList);
		PreNode(node.right,treeList);
		
	}
}

中序遍历:左子树,根结点,右子树

public static void MidNode(TreeNode node,List<int> treeList)
{
	if(node!=null)
	{
		MidNode(node.left,treeList);
		treeList.Add(node.val);
		MidNode(node.right,treeList);
	}
}

后序遍历:左子树,右子树,根结点

public static void EndNode(TreeNode node,List<int> treeList)
{
	if(node!=null)
	{
		EndNode(node.left,treeList);
		EndNode(node.right,treeList);
		treeList.Add(node.val);
		
	}
}

层次遍历:借助一个队列,先将根结点入队,然后根结点出队,每个结点出队时就访问该结点,且若其子树不为空则将其子树入队,然后每一层从左往右进行入队,直到队空。

public static void LevelNode(TreeNode node,List<int> treeList)
{
	if(node!=null)
	{
		Queue<int> queue=new Queue<TreeNode>();
		queue.Enqueue(node);
		
		TreeNode currentNode=null;
		while(queue.Count>0)
		{
			currentNode=queue.Dequeue();
			treeList.Add(currentNode.val);
			if(currentNode.left!=null)
			{
				queue.Enqueue(currentNode.left);
			}
			if(currentNode.right!=null)
			{
				queue.Enqueue(currentNode.right);
			}			
		}
		
	}
}

 

感谢参考博客:

https://www.cnblogs.com/zhao123/p/11138608.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值