笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2。首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大。其次所有结点的K2关键字满足优先队列(不妨设为最小堆)的顺序要求,即该结点的K2值比其子树中所有结点的K2值小。给定一棵二叉树,请判断该树是否笛卡尔树。
输入格式:
输入首先给出正整数N(≤1000),为树中结点的个数。随后N行,每行给出一个结点的信息,包括:结点的K1值、K2值、左孩子结点编号、右孩子结点编号。设结点从0~(N-1)顺序编号。若某结点不存在孩子结点,则该位置给出−1。
输出格式:
输出YES
如果该树是一棵笛卡尔树;否则输出NO
。
序号 | 输入 | 输出 | 说明 |
1 | 6 8 27 5 1 9 40 -1 -1 10 20 0 3 12 21 -1 4 15 22 -1 -1 5 35 -1 -1 | YES | 一般情况YES测试 |
2 | 6 8 27 5 1 9 40 -1 -1 10 20 0 3 12 11 -1 4 15 22 -1 -1 50 35 -1 -1 | NO | 一般情况NO测试 |
3 | 6 8 27 5 1 9 40 -1 -1 10 20 0 3 12 21 -1 4 11 22 -1 -1 5 35 -1 -1 | NO | K2满足最小堆顺序,但K1不满足二叉搜索树 |
4 | 9 11 5 3 -1 15 3 4 7 5 2 6 0 6 8 -1 -1 9 6 -1 8 10 1 2 1 2 4 -1 -1 20 7 -1 -1 12 9 -1 -1 | NO | K2满足最小堆顺序;K1的每个子树都满足二叉搜索树条件,但整棵树不满足二叉搜索树条件------即简单的后序遍历不能给出正确结果 |
5 | 1 1 1 -1 -1 | YES | 边界测试:最小N |
思路:判断每个节点的k1值是否大于其左子树的最大值,是否小于其右子树的最小值。若符合条件则为二叉搜索树
然后在判断每个节点的k2值是否小于其子树的最小值,若每个节点均符合,那么则为最小堆
既符合二叉搜索树又符合最小堆,那么输出YES,其他情况输出NO
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int k1,k2,l,r;
} t[1010];
int f1,f2;
int heapMin(int root)
{
if(root==-1)
return inf;
int l = t[root].l;
int r = t[root].r;
int data = t[root].k2;
data = min(heapMin(l),data);
data = min(heapMin(r),data);
return data;
}
int searchMin(int root)
{
if(root==-1)
return inf;
int l = t[root].l;
int r = t[root].r;
int data = t[root].k1;
data = min(searchMin(l),data);
data = min(searchMin(r),data);
return data;
}
int searchMax(int root)
{
if(root==-1)
return 0;
int l = t[root].l;
int r = t[root].r;
int data = t[root].k1;
data = max(searchMax(l),data);
data = max(searchMax(r),data);
return data;
}
int check(int root)
{
int l = t[root].l;
int r = t[root].r;
if(l!=-1)
{
if(searchMax(l)>t[root].k1)
{
return 0;
}
}
if(r!=-1)
{
if(searchMin(r)<t[root].k1)
{
return 0;
}
}
return 1;
}
int check2(int root)
{
int l = t[root].l;
int r = t[root].r;
int zMin = heapMin(l);
int yMin = heapMin(r);
if(zMin<t[root].k2)
{
return 0;
}
if(yMin<t[root].k2)
{
return 0;
}
return 1;
}
int main()
{
int n,i,k1,k2,l,r;
cin>>n;
int num=0;
for(i=1; i<=n; i++)
{
cin>>k1>>k2>>l>>r;
t[num].k1=k1,t[num].k2=k2,t[num].l=l,t[num++].r=r;
}
for(i=0;i<num;i++)
{
if(!check(i))
{
f1=1;
break;
}
if(!check2(i))
{
f2=1;
break;
}
}
if(f1||f2)
{
cout<<"NO"<<endl;
}
else
{
cout<<"YES"<<endl;
}
}