最短长度的珠子

题目要求和分析见题库

这儿只讲一点:p1和p2停下,得到序列,和当前最短序列比较完毕后,class为k-1(k为颜色数)。此时要保持class和color[],p1和p2重复那两个步骤,直至class再次等于k,会再次得到序列,再去和当前最短序列比较,如此循环。程序中止条件是p2越过最后一个元素循环至头一个元素(珠子是首尾相接的)


代码如下:

void shortest_chain(int a[], int n, int k){  //有n个珠子,共k个颜色,颜色代码为0到k-1
	assert(a != NULL);
	assert(n > 0);
	assert(k > 0 && k <= n);

	int color[k];
	int class = 0;
	int p = -1, q = -1;
	int len_min = n;
	int len_cur;
	int start, end;
	int over;
	memset(color, 0, k*sizeof(int));
	while(q < n){
		while(class < k){  //移动p将拥有颜色种类增至k
			p = (p+1)%n;
			if(color[a[p]] == 0) class++;
			color[a[p]]++;
		}
		over = 0;
		while(class > k-1){  //移动q将拥有颜色种类降至k-1,此时q和p之间即为候选最短序列
			q++;
			if(q == n){  //程序中止,如果q再前进相当于重复地从头开始,没有必要
				over = 1;
				break;
			}
			color[a[q]]--;
			if(color[a[q]] == 0) class--;
		}
                if(over == 1) break;  //程序中止
		else{
			len_cur = (p >= q) ? p-q+1 : n-(q-p+1)+2;  //计算长度,根据p和q的相对大小有两种情况
			if(len_cur < len_min){
				len_min = len_cur;
				start = q;
				end = p;
			}
		}
	}
        for(int i = start; i <= end; i = (i+1)%n)
                printf("%d ", a[i]);
	printf("\n");
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值