2021年蓝桥杯/算法训练/绘制地图

先上问题:
问题描述
  最近,WYF正准备参观他的点卡工厂。WYF集团的经理氰垃圾需要帮助WYF设计参“观”路线。现在,氰垃圾知道一下几件事情:
  1.WYF的点卡工厂构成一颗二叉树。
  2.一共有n座工厂。
  3.他需要把这颗树上的点以后序遍历的方法列出来,才能绘制地图。
  还好,最近他的属下给了他先序遍历和中序遍历的数据。可是,氰垃圾最近还要帮㊎澤穻解决一些问题,没有时间。请你帮帮他,替他完成这项任务。由于氰垃圾的一些特殊的要求,WYF的参观路线将会是这棵树的后序遍历。
输入格式
  第一行一个整数n,表示一共又n座工厂。
  第二行n个整数,表示先序遍历。
  第三行n个整数,表示中序遍历。
输出格式
  输出共一行,包含n个整数,为后序遍历。

**

思路讲解:

这是一个比较简单的二叉树遍历问题,给出先序遍历,中序遍历序列,要求输出后序遍历序列。
首先需要知道什么是二叉树的先序遍历、中序遍历和后续遍历。先序遍历是先根节点D、然后左孩子L、然后右孩子R,中   序遍历LDR,后序遍历LRD。注意,这里的遍历算法对每一个节点都是这样执行,还有不明白的同学可以参考严蔚敏老师的《数据结构》关于二叉树的内容,讲得很详细。
通过对这几种遍历方法的理解,我们可以知道,先序遍历序列给出了树的跟节点,中序遍历给出了树的左叶子节点。同时,由中序遍历我们可以知道,在序列中 根节点左边的部分就是根节点的左子树,右边的部分就是根节点的右子树,然后一颗子树的后序遍历又是同样的问题!!
至此,思路就已经很清晰了:找到根节点,确定子树,然后递归或者循环。我采用的是递归的方法。还有一些边界问题,我在代码中有注释,可以结合代码看。
import java.util.*;
//二叉树,给出先序遍历和中序遍历,输出后序遍历

/*
 * 基本思路:先序遍历的头元素即为整个二叉树的根节点,中序遍历的头元素是最左叶子节点
 * 按照中序遍历的算法,当遇到根节点时,即表示树的以便已经遍历完成,即
 * 中序遍历序列中,在整树根节点的左边的元素就在根节点左边,右边的树就在右边
 * 于是,这个问题就被分解为;两个子问题了。每一次确定树的左右之后,就得到了左右两颗子树
 * 而每颗子树的排列又是一样的问题,可以考虑递归算法
 * 值得主义的是,子树的边界是什么?
 * 二叉树,每一个根节点都有两个子节点,所以,子树的边界就是2
 * 即当最后一个子树只有两个元素时,递归就可以结束了
 * 按照先序排列的算法,既可以确定这两个元素的位置
 * 
 * 
 * 还有一个值得思考的问题是,如果根节点的左孩子和他一样呢?
 * 或者有孩子节点和他值相同呢?那么上面的方法就会出问题。
 * 这时候如何确定中序遍历序列是否完整遍历左树?
 * 
 * 一个可行的方法是在前面的基础上,比较先序遍历的子序列Arrays.copyOfRange(fst, 1, i+1)
 * 是否和中序遍历的Arrays.copyOfRange(mid, 0, i)相等,
 * 如果相等,证明这就是根节点,否则继续向后遍历
 * */
public class Tree {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		int n=sc.nextInt();
		int[] fst=new int [n];
		int[] mid= new int [n];
		for(int i=0;i<n;i++) {
			fst[i]= sc.nextInt();
		}
		for(int j=0; j<n;j++) {
			mid[j]= sc.nextInt();
		}
		sc.close();
		
		TreeSort(fst, mid);
		/*
		 * 我的代码老是不通过
		 * 爱报bug
		 * 你说啷个搞嘛
		 * 小错误好难得纠
		 * 憨了
		 * 逼着自己的大晚上写题
		 * 呜呜呜
		 * */
		
	}
	public static void TreeSort(int[] fst,int [] mid) {
		if(fst.length != mid.length) {
			return;
		}
		if(mid.length <= 2) {
			for(int i=0; i< mid.length; i++) {
				System.out.print(mid[i]+" ");
			}
			return;
		}
//		else {
//			System.out.print(mid[0]+" ");
//		}
		
//		int [] temp2, temp1;
		
		//左子树后序遍历输出
		for(int i=0;i<mid.length; i++) {
			int[] temp2=Arrays.copyOfRange(mid, 0, i);
			int [] temp1= Arrays.copyOfRange(fst, 1, i+1);
			Arrays.sort(temp1);
			Arrays.sort(temp2);
			
			
			//确定中序遍历序列中是否到达二叉树的根节点
			if(mid[i]== fst[0] && equl(temp1,temp2)) {
				/*
				 * 现在的问题是程序没有键入这个if结构
				 * 也就是if的判断条件不对
				 * 我怀疑是那个equals方法不对,不能正确比较两个数组是否相等
				 * 其余暂时没有发现问题
				 * 03/11
				 * */
				
				
				TreeSort(Arrays.copyOfRange(fst, 1, i+1), Arrays.copyOfRange(mid, 0, i));//左树
				
				TreeSort(Arrays.copyOfRange(fst, i+1, fst.length), Arrays.copyOfRange(mid, i+1, mid.length));
				System.out.print(fst[0]+" ");
				break;
			}
		}
//		System.out.print(fst[0]);
//		
	}//TreeSort()
	//写一个判断子树是否相等的函数,返回boolean值
	public static boolean equl(int[] s1,int[] s2) {
		if(s1.length != s2.length) {
			return false;
		}
		for(int i=0; i<s1.length;i++) {
			if(s1[i]!= s2[i]) {
				return false;
			}
		}
		
		return true;
	}
}

但是这个算法有个缺陷,就是时间复杂度太高,主要是equl()方法造成的,我没有想到更好的办法,使用数组的equals()方法不行。
临时写的一篇博客,也许漏洞百出,欢迎指正!

**

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值