一道百度试题

有一串首尾相连的珠子,共有m个,每一个珠子有一种颜色,并且颜色的总数不超过n(n<=10),求连续的珠子的颜色总数为n时,长度最小的区间。可简述思路或者给出伪代码,并且给出时间和空间复杂度分析。(baidu 2011校园招聘笔试题目)

只能求出一个解来,很难做到最优解。

思路是:

1.将串换为一个个的集合,每一个集合为一组相邻且不重复的颜色组成。(这里颜色用数组表示)

2.依据集合中颜色数目的多少插入到Beadinfo数组中。

3.将不同集合中的Bit进行与操作,如果为OKOK,则说明两个集合中的颜色组合可以为n。


目前,在useassemble中仅仅将不同颜色最多的集合与别的集合进行合并查看,如果找到就返回区间距离,这种做法不能保证找到最小区间,甚至也不能保证能找到一个颜色总数为n的区间。

//有100个珠子
#define TOTAL 30
#define CORLOR	6
char OKOK = ((0x01<<1)|(0x01<<2)|(0x01<<3)|(0x01<<4)|(0x01<<5)|(0x01<<6));

int Bead[TOTAL];

struct info{
	char num;	//有几个连续的相等
	char bit;	//缺失那一个?
	short start;//在Bead数组中的开始位置
};

struct info Beadinfo[TOTAL];
int infosize = 0;


void getBead(){
	int i;
	srand( (unsigned)time( NULL ) );
	for(i = 0; i < TOTAL; i++){
		Bead[i] = rand()%CORLOR + 1;
		printf("%d  ", Bead[i]);
	}
}

void init_Breadinfo(){
	int i;
	for(i = 0; i < TOTAL; i++){
		Beadinfo[i].start = -1;
	}
}
//插入排序法,最大的放在最前
void insertBeadinfo( struct info a ){
	int i = 0;
	int j = 0;
	//if( Beadinfo[0].start == -1 ){
	//	Beadinfo[0] = a;
	//	infosize++;
	//	return ;
	//}
	while( i< infosize ){
		if(a.num>Beadinfo[i].num)
			break;
		i++;
	}
	for(j = infosize -1;j !=i-1;j--){
		Beadinfo[j+1] = Beadinfo[j];
	}
	Beadinfo[i] = a;
	infosize++;
}

void preassemble(int *a, int size){
	int i = 0;
	int* pre = a;
	int* tail = a;
	struct info tmp;
	tail++;
	while( tail < a + size ){
		tmp.start = pre - a;
		tmp.bit = 0x01<<(*pre);
		while( (tmp.bit & 0x01<<*tail) == 0 && ( tail < a + size ) ){
			tmp.bit |= 0x01<<(*tail);
			tail++;
		}
		tmp.num = tail - pre;
		insertBeadinfo(tmp);
		//Beadinfo[infosize++] = tmp;
		while(*pre!=*tail)pre++;
		pre++;
		tail = pre+1;
	}
	//因为是环形,所以让首位相接  暂不考虑
	//tail = a + size - 1;
	//if( *tail == *a )
	//	return ;
	//tmp = Beadinfo[0];
	//while( (tmp.bit & 0x01<<*tail) == 0 ){
	//	tmp.bit |= 0x01<<(*tail);
	//	tail--;
	//}
	//tmp.num += a + size - tail -1;
	//tmp.start = tail - a + 1;
	//insertBeadinfo(tmp);
}

void viewassemble(){
	int i;
	printf("\nbeadinfo:\n");
	for(i = 0; i < infosize; i++){
		printf("start:%d , num%d\n", Beadinfo[i].start, Beadinfo[i].num);
	}
}

int useassemble(){
	int i = 0;
	char bit = 0;
	int j,k;
	for( k = 0; k<infosize-1;k++){
	for( i=k; i < infosize-1; i++ ){
		if( (Beadinfo[k].bit|Beadinfo[i+1].bit) ==OKOK ){
			if( Beadinfo[i+1].start > Beadinfo[k].start ){
				j = Beadinfo[k].start;
				while( bit!=OKOK ){
					bit |= 0x01<<Bead[j];
					j++;
				}
				printf("start at %d end at %d", Beadinfo[k].start, j-1);
				j -= Beadinfo[k].start;
				return j > (TOTAL-j)?(TOTAL-j):j;
			}
			else{
				j = Beadinfo[k].start + Beadinfo[k].num -1;
				if( j > TOTAL){
					//这里也可能出现错误
				}else{
				while( bit!=OKOK ){
					bit |= 0x01<<Bead[j];
					j--;
				}
				printf("start at %d end at %d", j+1, Beadinfo[k].start + Beadinfo[k].num -1);
				j = Beadinfo[k].start + Beadinfo[k].num - j -1;
				return j > (TOTAL-j)?(TOTAL-j):j;	
				}
			}
		}
	}
	}
}

int main(int argc, char **argv)
{
	int num = TOTAL;
	getBead();
	init_Breadinfo();
	preassemble(Bead, num);
	viewassemble();
	useassemble();
	return 0;
}

程序运行结果大致为:

2  1  3  1  4  4  5  1  3  3  5  1  1  5  5  6  2  1  5  2  5  4  6  1  6  4  5  5  5  5
beadinfo:
start:19 , num5
start:5 , num4
start:14 , num4
start:15 , num4
start:23 , num4
start:0 , num3
start:2 , num3
start:9 , num3
start:17 , num3
start:12 , num2
start:27 , num1
start:28 , num1
start at 9 end at 23

其中的
start:19 , num5  即对应数组中的:2 5 4 6 1
start at 9 end at 23,即在这一串中包含了所有颜色:
3  5  1  1  5  5  6  2  1  5  2  5  4  6  1

如果你对实现很感兴趣,可以参考:

http://www.spongeliu.com/%E7%AE%97%E6%B3%95/baidu2011/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值