7-65 笛卡尔树 (25分)(非常规做法+完整思路+极简代码)

在这里插入图片描述
在这里插入图片描述
写在前面:看到这个题,感觉并不难。算是模板题。不过翻看了一下网上的题解,基本上全是常规的建立一个二叉搜索树,建立一个小顶堆(也可以用优先队列)。然后分别遍历判断。当然,我比较懒,就没去建树建堆。

思路:首先建立结构体数组来存储每个节点的k1,k2,左右孩子编号。然后在接受数据的时候,用一个前驱数组pre[]来存储每个结点的前驱结点,不仅可以用这个数组找到根还可以用它遍历判断,这样就可以不用建树建堆了。。哈哈哈哈。。具体操作如下:
1.首先遍历一遍pre,如果那个值是-1,说明它是根。
2.判断小顶堆:遍历pre数组 只要判断这个结点是不是比它前驱结点的k2值大就行了。
3.判断二叉搜素树:同样用pre数组来遍历,只不过要用到DFS来进行一次中序遍历,因为二叉搜索树中序遍历序列是一个递增的序列,这样只用判断这个序列是不是每个数都比后面数小就行。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,pre[1010];
vector<int>v;
struct node
{
	int k1,k2,left,right,id;
}p[1010];
void read()
{
	memset(pre,-1,sizeof pre);
	cin>>n;
	for(int i=0;i<n;i++)
	{
		int a,b,c,d;
		cin>>a>>b>>c>>d;
		p[i].k1=a;	p[i].k2=b;
		p[i].left=c;	p[i].right=d;	p[i].id=i;
		if(c!=-1)	pre[c]=i;
		if(d!=-1)	pre[d]=i;
	}
}
void dfs(int num)
{
	if(num==-1)	return ;
	else
	{
		dfs(p[num].left);
		v.push_back(p[num].k1);
		dfs(p[num].right);
	}
}
bool check2()
{
	int t=-1,flag=1;
	for(int i=0;i<n;i++)
		if(pre[i]==-1)	
		{
			t=i;
			break;
		}
	dfs(t);
	for(int i=0;i<n-1;i++)
		if(v[i]>v[i+1])
		{
			flag=0;
			break;
		}
	if(flag)	return true;
	return false;
}	
bool check1()
{
	for(int i=0;i<n;i++)
	{
		if(pre[i]==-1)	continue;
		if(p[i].k2<p[pre[i]].k2)	return false;
	}
	return true;
}
int main()
{
	read();
	if(check1()&&check2())	cout<<"YES";
	else	cout<<"NO";
}
发布了180 篇原创文章 · 获赞 22 · 访问量 9019

猜你喜欢

转载自blog.csdn.net/qq_44622401/article/details/104237680