我发现了这个问题:
考虑36位的序列。每个这样的序列有32位5位 由相邻位组成的序列。例如,序列 1101011 ...包含5位序列11010,10101,01011,.......写一个 程序打印具有两个属性的所有36位序列: 1.序列的前5位是00000。 2.没有两个5位子序列是相同的。
因此我推广了所有具有k位唯一子序列的n位序列,以满足上述要求。然而,我能想到的唯一方法是使用残酷的力搜索:生成n比特序列的所有排列,其中前k个比特为零,然后对于每个序列,检查所有k比特子序列是否唯一。这显然不是一种非常有效的方法。我想知道有没有更好的方法来解决这个问题?
感谢。
答案 0 :(得分:3)
最简单的方法似乎是一种回溯方法。您可以跟踪您使用平面阵列看到的5位序列。在每一位,尝试添加0 - counter = (counter & 0x0f) << 1
并检查您之前是否已经看过,然后执行counter = counter | 1
并尝试该路径。
可能有更高效的算法可以更快地修剪搜索空间。这似乎与https://en.wikipedia.org/wiki/De_Bruijn_sequence有关。我不确定,但我相信它实际上是等同的;也就是说,序列的最后五位必须是10000
,使其成为循环。
#include <stdio.h>
#include <stdlib.h>
char *binprint(int val) {
static char res[33];
int i;
res[32] = 0;
for (i = 0; i < 32; i++) {
res[31 - i] = (val & 1) + '0';
val = val >> 1;
}
return res;
}
void checkPoint(int mask, int counter) {
// Get the appropriate bit in the mask
int idxmask = 1 << (counter & 0x1f);
// Abort if we've seen this suffix before
if (mask & idxmask) {
return;
}
// Update the mask
mask = mask | idxmask;
// We're done if we've hit all 32
if (mask == 0xffffffff) {
printf("%10u 0000%s\n", counter, binprint(counter));
return;
}
checkPoint(mask, counter << 1);
checkPoint(mask, (counter << 1) | 1);
}
void main(int argc, char *argv[]) {
checkPoint(0, 0);
}
答案 1 :(得分:2)
我记得在我的编程面试问题书中看到了这个确切的问题。这是他们的解决方案:
希望它有所帮助。欢呼声。