There is a kind of balanced binary search tree named red-black tree in the data structure. It has the following 5 properties:
- (1) Every node is either red or black.
- (2) The root is black.
- (3) Every leaf (NULL) is black.
- (4) If a node is red, then both its children are black.
- (5) For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.
For example, the tree in Figure 1 is a red-black tree, while the ones in Figure 2 and 3 are not.
Figure 1 | Figure 2 | Figure 3 |
For each given binary search tree, you are supposed to tell if it is a legal red-black tree.
Input Specification:
Each input file contains several test cases. The first line gives a positive integer K (≤30) which is the total number of cases. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the preorder traversal sequence of the tree. While all the keys in a tree are positive integers, we use negative signs to represent red nodes. All the numbers in a line are separated by a space. The sample input cases correspond to the trees shown in Figure 1, 2 and 3.
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
C++:
建树过程中判断:
/*
@Date : 2018-03-07 08:39:51
@Author : 酸饺子 (changzheng300@foxmail.com)
@Link : https://github.com/SourDumplings
@Version : $Id$
*/
/*
https://www.patest.cn/contests/pat-a-practise/1135
思路:
先根据先序遍历序列建BST树,如果建树的过程中发现不是BST则直接返回;
在建树的同时记录每个结点的黑高度,如果左右子树黑高度不等则表示条件4不满足
然后层序遍历判断条件4
*/
#include <iostream>
#include <cstdio>
#include <memory>
#include <cmath>
#include <queue>
using namespace std;
struct TNode
{
int data;
shared_ptr<TNode> left = nullptr, right = nullptr;
int blackH = 0;
};
static bool isBST = true;
static bool isRB = true;
shared_ptr<TNode> build_tree(shared_ptr<TNode> T, int pre[], int preB, int preE)
{
if (preB == preE || !isRB || !isBST) return T;
int root = pre[preB];
T = make_shared<TNode>();
T->data = root;
if (preB + 1 == preE)
{
if (T->data > 0) T->blackH = 1;
return T;
}
int lLength = preE - preB - 1;
for (int i = preB + 1; i != preE; ++i)
{
if (lLength == preE - preB - 1 && abs(pre[i]) > abs(root))
lLength = i - preB - 1;
if (lLength != preE - preB - 1)
{
if (abs(pre[i]) <= abs(root))
{
isBST = false;
return T;
}
}
}
T->left = build_tree(T->left, pre, preB + 1, preB + 1 + lLength);
T->right = build_tree(T->right, pre, preB + 1 + lLength, preE);
int hl = T->left ? T->left->blackH : 0;
int hr = T->right ? T->right->blackH : 0;
if (hl != hr) isRB = false;
else T->blackH = T->data > 0 ? hl + 1 : hl;
return T;
}
bool judge(shared_ptr<TNode> T)
{
if (!isBST || !isRB || T->data < 0) return false;
queue<shared_ptr<TNode>> Q;
Q.push(T);
while (!Q.empty())
{
auto node = Q.front(); Q.pop();
if (node->left)
{
if (node->data < 0 && node->left->data < 0) return false;
Q.push(node->left);
}
if (node->right)
{
if (node->data < 0 && node->right->data < 0) return false;
Q.push(node->right);
}
}
return true;
}
int main(int argc, char const *argv[])
{
int K, N;
scanf("%d", &K);
while (K--)
{
scanf("%d", &N);
int pre[N];
for (int i = 0; i != N; ++i)
scanf("%d", &pre[i]);
shared_ptr<TNode> T = nullptr;
isBST = isRB = true;
T = build_tree(T, pre, 0, N);
if (judge(T)) printf("Yes\n");
else printf("No\n");
}
return 0;
}
后序遍历计算黑高度判断:
/*
@Date : 2018-09-05 23:10:38
@Author : 酸饺子 (changzheng300@foxmail.com)
@Link : https://github.com/SourDumplings
@Version : $Id$
*/
/*
https://pintia.cn/problem-sets/994805342720868352/problems/994805346063728640
*/
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int K;
const int MAXN = 35;
int pre[MAXN];
struct TreeNode
{
TreeNode() = default;
TreeNode(int k, bool black_): key(k), black(black_) {}
int key;
bool black = true;
int blackHeight = -1;
TreeNode *left = nullptr, *right = nullptr;
};
TreeNode* build_tree(int b, int e)
{
if (e == b)
return nullptr;
int k = pre[b];
bool black = true;
if (k < 0)
{
k = -k;
black = false;
}
TreeNode *r = new TreeNode(k, black);
if (b + 1 == e)
return r;
int leftE = e;
for (int i = b + 1; i != e; ++i)
{
if (abs(pre[i]) >= k)
{
leftE = i;
break;
}
}
r->left = build_tree(b+1, leftE);
r->right = build_tree(leftE, e);
return r;
}
int get_black_height(TreeNode *r)
{
int ret = 0;
if (r)
{
if (r->blackHeight != -1)
ret = r->blackHeight;
else
{
int lH = get_black_height(r->left);
int rH = get_black_height(r->right);
if (lH != rH)
ret = -2;
else
{
if (r->black)
{
ret = lH + 1;
}
else
{
ret = lH;
}
}
}
}
return ret;
}
bool post_order_traversal(TreeNode *T)
{
bool ret = true;
if (T)
{
bool ret1 = post_order_traversal(T->left);
bool ret2 = post_order_traversal(T->right);
T->blackHeight = get_black_height(T);
if (T->blackHeight == -2)
ret = false;
else
{
if (!T->black && ((T->left && !T->left->black) || (T->right && !T->right->black)))
ret = false;
else
{
ret = ret1 && ret2;
}
}
}
return ret;
}
bool judge(TreeNode *T)
{
bool ret = true;
if (!T->black)
ret = false;
else
{
ret = post_order_traversal(T);
}
return ret;
}
int main()
{
scanf("%d", &K);
while (K--)
{
int N;
scanf("%d", &N);
TreeNode *T = nullptr;
for (int i = 0; i != N; ++i)
scanf("%d", &pre[i]);
T = build_tree(0, N);
if (judge(T))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
return 0;
}