E3-F-姜-二叉树

题目描述

俗话说得好,姜还是老的辣。

HolmiumTS很喜欢种姜,但他自己却从来不吃姜。他年初的时候往土里埋了一块姜。

每隔一段时间,他就会把土里的姜全部挖出来,每一块都切成两半,然后再埋进土里。每次埋之前,他都会测定每一块姜的辣度。

经过k次之后,他得到了一棵有2k个叶子的完全二叉树,每个结点都记录了对应姜的辣度,他称之为“族谱”。

现在有两张这样的“族谱”,你需要判断两张“族谱”是否相等。

“族谱”相等的定义:

1、对于在族谱叶子上的姜,如果他们的辣度相同则相等。

2、对于其它的姜,如果他们的辣度相等且他们产生的仔姜的辣度也对应相等,则他们相等。(这里的对应不要求顺序,即一块的左侧仔姜可以对应另一块的右侧仔姜)

3、如果一块姜在族谱的叶子上而另一块不在叶子上,则他们不相等。

4、两份族谱相等当且仅当两份族谱位于根的姜相等。

输入
第一行包含一个整数,为数据的组数T
接下来包含3T行,每三行对应一组数据

每组数据第一行包含一个整数k,含义见题目描述。

接下的两行每行包含2(k+1)−1个非负整数,对应一份族谱的层次遍历。

输出
对于每组数据,输出Yes或No,表示族谱是否相同。

输入样例

2
1
1 2 3
1 3 2
2
1 2 2 3 3 4 4
1 2 2 3 4 3 4

输出样例

Yes
No

数据范围与约定
1<=T<=100
1<=k<=10
保证辣度非负且在int范围内

提示
两份族谱能否转成一个易于判断的族谱形式?

问就是不吃葱姜蒜.jpg

思路分析

根据助教的Hint(Hint每次都让迷惑的我更加迷惑2333),把数组转化成容易判断的二叉树本树形式。
再用从根节点处依次递归,判断两个二叉树是否相等(不得不说虽然菜鸡的我难以掌握递归,但它真的太强辽)

AC代码

#include<stdio.h>
#include<stdlib.h>

struct node{
	int data;
	struct node *lchild,*rchild;
};
typedef struct node Node;
typedef struct node *Nodeptr;

int nums_a[2100], nums_b[2100];

Nodeptr Create(int a[],int i,int n);//生成二叉树
int isEqual(Nodeptr t1,Nodeptr t2);//判断两个二叉树是否相等

int main()
{
	int i,t,k,n=1;
	scanf("%d",&t);
	while(t--)
	{
		n=1;
		scanf("%d",&k);
		for(i=0;i<k+1;i++)
		  n*=2;
		n--;
		for(i=0;i<n;i++)
		  scanf("%d",&nums_a[i]);
		for(i=0;i<n;i++)
		  scanf("%d",&nums_b[i]);
		Nodeptr head_a = NULL, head_b = NULL;
		head_a = Create(nums_a,0,n);
		head_b = Create(nums_b,0,n);
		if(isEqual(head_a,head_b)==1) printf("Yes\n");
		else printf("No\n");
	}
}
Nodeptr Create(int a[],int i,int n)
{
	if(i>=n)  return NULL;
	Nodeptr t = (Nodeptr)malloc(sizeof(Node));
	t->data=a[i];
	t->lchild = Create(a,2*i+1,n);
	t->rchild = Create(a,2*i+2,n);
	return t;
}
int isEqual(Nodeptr t1,Nodeptr t2)
{
	if(t1==NULL&&t2==NULL) return 1;
	if(t1==NULL||t2==NULL) return 0;
	if(t1->data==t2->data)
	{
		return (isEqual(t1->lchild,t2->lchild)&&isEqual(t1->rchild,t2->rchild))||(isEqual(t1->lchild,t2->rchild)&&isEqual(t1->rchild,t2->lchild));
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值