1135. Is It A Red-Black Tree-PAT甲级
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 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 17Sample Output:
Yes No No
分析:
这道题一开始使用先序不建树测试点1过不去,找了好久问题发现不建树不适合有重复节点的树,这是因为不建树去遍历一棵树时中序序列的下标并不是唯一的,会导致子树的划分出现错误,从而陷入无限循环,提交代码测试点1段错误,由此推断测试点1数据可能有重复节点。
建树AC,先建树再DFS遍历树,judgeRBT两个参数分别是,root与父节点颜色par_color。使用par_color将连续两个节点是否都为红色与根节是否红色合成一个判断条件,初始将父节点的颜色设置为-1即红色,如果根节点为红色则is2Red为true即有两个连续的红色则不为二叉树。记录每一条path上黑色节点的数目bnode,当到达叶子节点时将bnode黑色节点数目插入一个set即isRep,若所有path的bnode一致,则set的大小最终为1。最终DFS遍历完一棵树,得到is2Red与isRep.size()。is2Red==false&&isRep.size()==1时说明是一颗红黑树输出Yes。
建树AC代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
using namespace std;
set<int> isRep; //用来判断所有路径黑色节点个数是否一定
vector<int> pre;
int bnode, n, is2Red; //bnode记录某一路径黑色节点数,is2Red是否有两个连续的红色父子
struct Node
{
int data;
Node *lchild, *rchild;
Node(int x) : data(x), lchild(NULL), rchild(NULL){};
};
void create(Node *&root, int v)
{
if (root == NULL)
root = new Node(v);
else if (abs(v) <= abs(root->data))
create(root->lchild, v);
else
create(root->rchild, v);
}
void judgeRBT(Node *root, int par_color)
{
if (root == NULL)
{
isRep.insert(bnode);
return;
}
if (root->data < 0 && par_color < 0)
is2Red = true;
if (root->data > 0)
bnode++;
judgeRBT(root->lchild, root->data);
judgeRBT(root->rchild, root->data);
if (root->data > 0)
bnode--;
}
int main()
{
int k;
cin >> k;
for (int i = 0; i < k; i++)
{
scanf("%d", &n);
isRep.clear();
is2Red = false;
bnode = 0;
pre.resize(n);
Node *root = NULL;
for (int j = 0; j < n; j++)
{
scanf("%d", &pre[j]);
build(root, pre[j]);
}
judgeRBT(root, -1);
//若父子节点无连续红色且各个路径黑色节点一定时输出Yes
printf("%s\n", ((!is2Red && (isRep.size() == 1)) ? "Yes" : "No"));
}
return 0;
}
不建树测试点1段错误代码
#include <iostream>
#include <cstdio>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;
set<int> isRep; //用来判断所有路径黑色节点个数是否一定
vector<int> pre, in;
int bnode, n; //用来记录某一路径黑色节点数
bool is2Red; //检测是否有两个连续红色
void judgeRBTree(int par_color, int inl, int inr, int pre_root)
{
if (inl <= inr)
{
if (par_color < 0 && pre[pre_root] < 0)
is2Red = true;
int in_root = 0;
while (pre[pre_root] != in[in_root])
in_root++;
//如果左孩子是黑色则bnode++
if (inl <= in_root - 1 && pre[pre_root + 1] > 0)
bnode++;
judgeRBTree(pre[pre_root], inl, in_root - 1, pre_root + 1);
if (inl <= in_root - 1 && pre[pre_root + 1] > 0)
bnode--;
//如果右孩子是黑色则bnode++
if (in_root + 1 <= inr && pre[in_root - inl + pre_root + 1] > 0)
bnode++;
judgeRBTree(pre[pre_root], in_root + 1, inr, in_root - inl + pre_root + 1);
if (in_root + 1 <= inr && pre[in_root - inl + pre_root + 1] > 0)
bnode--;
}
else
{
//将这一路径上的黑节点数插入rep
isRep.insert(bnode);
return;
}
}
int main()
{
int k;
cin >> k;
for (int i = 0; i < k; i++)
{
scanf("%d", &n);
isRep.clear();
pre.resize(n);
in.resize(n);
is2Red = false;
bnode = 0;
for (int j = 0; j < n; j++)
{
scanf("%d", &pre[j]);
in[j] = pre[j];
}
sort(in.begin(), in.end(), [](int a, int b) { return abs(a) < abs(b); });
judgeRBTree(-1, 0, n - 1, 0);
//若父子节点无连续红色且,各个路径黑色节点一定时输出Yes
printf("%s\n", ((!is2Red && (isRep.size() == 1)) ? "Yes" : "No"));
}
return 0;
}

浙公网安备 33010602011771号