PAT 甲级 1135 Is It A Red-Black Tree (30 分)【不建树版】

不想建树,于是自己琢磨了半天,最终只过了3个测试点,29分,测试点3的1分不知道卡在哪了(哭泣TT)。欢迎各位大佬来吊打我!!

基本思路:红黑树首先是BST,所以它的中序遍历就是先序遍历序列按从小到大排序,在这里是绝对值从小到大。有了先序和中序,就可以对树进行模拟先序遍历了。
根据红黑树的性质,需要对树进行3个判断:

  1. 根是否是正数;
  2. 红色节点是否有两个黑色子节点;
  3. 每条从根到叶的路径上黑色节点数是否相同。

对于1, 只需要判断pre[0]>0即可。
对于2,用func1来判断。红色节点必须有两个黑色孩子节点,只有一个孩子或者任一孩子是红色的都不行。
对于3,用func2来判断。两个func都是先访问根,再递归调用左子树和右子树,因此是模拟的先序遍历。

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;

vector<int> pre, in;

bool cmp(int a, int b){
	return abs(a)<abs(b);
}
bool func1(int inL, int inR, int preRoot){
	if(inL>=inR) return true;
	int r=pre[preRoot], i;
	for(i=inL;i<=inR;i++)
		if(in[i]==r) break;
	if(r<0){
		if(i==inL||i==inR) return false;
		else if(pre[preRoot+1]<0||pre[preRoot+i-inL+1]<0) return false;
	}
	if(func1(inL, i-1, preRoot+1)) return func1(i+1, inR, preRoot+i-inL+1);
	else return false;
}

int func2(int inL, int inR, int preRoot){
	int r=pre[preRoot], i;
	if(inL>=inR){
		if(r>0) return 1;
		else return 0;
	}
	for(i=inL;i<=inR;i++){
		if(in[i]==r) break;
	}
	if(i!=inL&&i!=inR){
		if(func2(inL, i-1, preRoot+1)==func2(i+1, inR, preRoot+i-inL+1)){
			if(r>0) return func2(inL, i-1, preRoot+1)+1;
			else return func2(inL, i-1, preRoot+1);
		}
		else return i-999;
	}
	else if(i!=inL) return func2(inL, i-1, preRoot+1)+1;
	else return func2(i+1, inR, preRoot+i-inL+1)+1;
}

int main(){
	int K, N;
	cin>>K;
	for(int i=0;i<K;i++){
		cin>>N;
		pre.resize(N);
		in.resize(N);
		for(int j=0;j<N;j++){
			cin>>pre[j];
			in[j]=pre[j];
		}
		sort(in.begin(), in.end(), cmp);
		if(pre[0]>0&&func1(0, N-1, 0)&&(func2(0, N-1, 0)>0)) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值