有一串首尾相连的珠子,共有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/