一、题目描述
Input Specification:
Output Specification:
For each test case, print in a line “Yes” if the given tree is a red-black tree, or “No” if not.
Sample Input:
3
9
7 -2 1 5 -4 -11 8 14 -15
9
11 -2 1 -7 5 -4 8 14 -15
8
10 -7 5 -6 8 15 -11 17
Sample Output:
Yes
No
No
二、解题思路
比起红黑树的题目,这道题更像是一道模拟题,把红黑树的定义给我们,然后给出一棵BST树的前序遍历序列,让我们判断这棵树是不是红黑树。事实上我们要做的就是做两个判断,一个就是红色结点是否有红色的孩子,另外一个就是对于任意一个结点,到达每个叶子结点经过的黑色结点数目是否一致。对于两个judge函数,我们都用了递归的方式,不难理解。
三、AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
vector<int> arr;
struct node
{
int val;
struct node *left, *right;
};
node* build(node *root, int v) //构建红黑树
{
if(root == NULL)
{
root = new node();
root->val = v;
root->left = NULL;
root->right = NULL;
}
else if(abs(v) <= abs(root->val))
root->left = build(root->left, v);
else
root->right = build(root->right, v);
return root;
}
bool judge1(node* root)
{
if(root == NULL) return true;
if(root->val < 0) //红色结点不会有红色的孩子
{
if(root->left != NULL && root->left->val < 0) return false;
if(root->right != NULL && root->right->val < 0) return false;
}
return judge1(root->left) && judge1(root->right);
}
int getNum(node *root) //得到从当前结点到叶子结点经过的黑色结点数
{
if(root == NULL) return 0;
int l = getNum(root->left);
int r = getNum(root->right);
return root->val > 0 ? max(l, r) + 1 : max(l, r);
}
bool judge2(node *root) //判断到达每个叶子结点经过的黑色结点数是否相同
{
if(root == NULL) return true;
int l = getNum(root->left);
int r = getNum(root->right);
if(l != r) return false;
return judge2(root->left) && judge2(root->right);
}
int main()
{
int n, k;
scanf("%d", &k);
for(int i=0; i<k; i++)
{
scanf("%d", &n);
arr.resize(n);
node *root = NULL;
for(int j=0; j<n; j++)
{
scanf("%d", &arr[j]);
root = build(root, arr[j]);
}
if(arr[0] < 0 || judge1(root) == false || judge2(root) == false)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}