POJ 1002 487-3279

刚看完这道题,我的第一反应是用散列表。对每行输入求标准格式,用后4位做为hash值,前3位最为特征值,用链表的方式处理冲突。

但写到一半,感觉自己2了。考虑最坏情况,先读入1000个有相同hash值,不同特征值的号码,然后重复最后一个数。

此时散列的时间会用到100000*1000,目测TLE。需要用6位做为hash值,1位做为特征值才能做到10^6的时间复杂度,还可能MLE。

又注意到总共才100000个读入,O(N*lgN)的时间复杂度够用,突然觉得,何必这么麻烦。

于是我改写了一个快排算法,然后。。。。。。

不是我长得太丑就是POJ数据太丑!反正我一直TLE,随机化快排也不行!

当时我的内心是崩溃的。

上网搜了一下,瞬间感觉智商被碾压了。

一篇利用STL秒做的文章

认真学习了map的数据结构之后,发现,这货时间复杂度不也是O(N*lgN)吗!

一怒之下,手撸红黑树,现在想想,都是泪啊。

//PKU_1002
//快速排序会超时
//利用红黑树实现

#include <iostream>
using namespace std;

class RB_Tree_Node{
public:
	char color;
	RB_Tree_Node * left,* right,* parent;
	int key;
	int num;
};

class RB_Tree{
public:
	RB_Tree_Node * root,* nil;

	RB_Tree() {
		nil = new RB_Tree_Node;
		nil->left=nil->right=nil->parent=nil;
		nil->color='N';
		root=nil;
	}

	~RB_Tree(){
		delete nil;
	}

	void left_rotate(RB_Tree_Node * p) {
		RB_Tree_Node * y = p->right;

		p->right = y->left;
		if (y->left!=nil)
			y->left->parent=p;

		y->parent = p->parent;
		if (p->parent==nil)
			root = y;
		else if (p==p->parent->left)
			p->parent->left = y;
		else
			p->parent->right = y;

		y->left = p;
		p->parent  = y;
	}

	void right_rotate(RB_Tree_Node * p) {
		RB_Tree_Node * y = p->left;
		
		p->left = y->right;
		if (y->right!=nil)
			y->right->parent=p;

		y->parent = p->parent;
		if (p->parent==nil)
			root = y;
		else if (p==p->parent->left)
			p->parent->left = y;
		else
			p->parent->right = y;
		
		y->right = p;
		p->parent = y;
	}

	void insert(RB_Tree_Node * p) {
		RB_Tree_Node * x,* y;
		x = root;
		y = nil;
		while (x!=nil) {
			y=x;
			if (p->key<x->key)
				x=x->left;
			else
				x=x->right;
		}
		p->parent = y;
		if (y==nil)
			root=p;
		else if (p->key<y->key)
			y->left=p;
		else
			y->right=p;
		p->left=nil;
		p->right=nil;
		p->color='R';

		while (p->parent->color=='R')
			if (p->parent==p->parent->parent->left){
				y=p->parent->parent->right;
				if (y->color=='R'){
					p->parent->color='B';
					y->color='B';
					p->parent->parent->color='R';
					p=p->parent->parent;
				}
				else if (p==p->parent->right){
					p=p->parent;
					left_rotate(p);
				}
				else {
					p->parent->color='B';
					p->parent->parent->color='R';
					right_rotate(p->parent->parent);
				}
			}
			else{
				y=p->parent->parent->left;
				if (y->color=='R'){
					p->parent->color='B';
					y->color='B';
					p->parent->parent->color='R';
					p=p->parent->parent;
				}
				else if (p==p->parent->left){
					p=p->parent;
					right_rotate(p);
				}
				else {
					p->parent->color='B';
					p->parent->parent->color='R';
					left_rotate(p->parent->parent);
				}
			}
		root->color='B';
	}

	RB_Tree_Node * next(RB_Tree_Node * p){
		if (p->right!=nil){
			p=p->right;
			while (p->left!=nil)
				p=p->left;
		}
		else if (p==p->parent->left){
			return p->parent;
		}
		else {
			while (p==p->parent->right)
				p=p->parent;
			p=p->parent;
		}
		return p;
	}

	RB_Tree_Node * begin(){
		RB_Tree_Node * p=root;
		while (p->left!=nil)
			p=p->left;
		return p;
	}

	RB_Tree_Node * end(){
		RB_Tree_Node * p=root;
		while (p->right!=nil)
			p=p->right;
		return p;
	}

	RB_Tree_Node * find(int k,RB_Tree_Node * p){
		if (p==nil) return p;
		if (p->key==k)	return p;
		else if (p->key>k)	return find(k,p->left);
		else return find(k,p->right);
	}
};


int main(){
	char ch;
	int i,n,hash;
	RB_Tree T;
	RB_Tree_Node * p;

	cin>>n;
	getchar();
	for(i=0;i<n;i++) {
		//计算每行读入的hash值
		hash=0;
		do{
			ch=getchar();
			if (ch>='0' && ch<='9')
				hash=hash*10+ch-'0';
			else if (ch>='A' && ch<='P')
				hash=hash*10+(int(ch)-'A')/3+2;
			else if (ch>='R' && ch<='Y')
				hash=hash*10+(int(ch)-'B')/3+2;
		}
		while (ch!='\n');
		p=T.find(hash,T.root);
		if (p->color=='N'){
			p = new RB_Tree_Node;
			p->key=hash;
			p->num=0;
			T.insert(p);
		}
		p->num++;
	}

	bool flag=true;
	p=T.begin();
	while (p->color!='N'){
		if (p->num>1) {
			hash=p->key;
			flag=false;

			if (hash<100000)
				cout<<"00";
			else if (hash<1000000)
				cout<<"0";
			cout<<hash/10000<<"-";
			hash%=10000;
			if (hash<10)
				cout<<"000";
			else if (hash<100)
				cout<<"00";
			else if (hash<1000)
				cout<<"0";
			cout<<hash<<' '<<p->num<<endl;
		}
		p=T.next(p);
	}
	if (flag)
		cout<<"No duplicates."<<endl;

	return 0;
}

等冷静下来,才真的想要剁手,电话号码由‘0’-‘9’这10个字符组成,长度固定为7位,总共100000个数据,7*100000<10^6,简直是摆好姿势让你基数排序啊!

然后我又看了看这200+行的代码,果断的——

下一题!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值