如何仅用位运算高效枚举无相邻置位的N长位向量(N≤64)
高效枚举无相邻置位的N位向量(仅位运算、非递归)
要高效枚举长度为N(N≤64)且无相邻1的位向量,核心是**直接生成符合条件的数,而非遍历所有2N个数再筛选**,时间复杂度为O(F(N+2))(F为斐波那契数列),远低于朴素方法的O(N*2N)。
核心思路
无相邻1的N位二进制数,本质是不含连续1的数,这类数的总数是斐波那契数列的第N+2项(例如N=4时总数为8,对应F(6)=8)。我们可以通过位运算直接生成每个符合条件的数,无需递归或全量遍历。
逐一生成法(适合N≤64)
这种方法通过位运算快速计算当前数的下一个符合条件的数,无需存储所有结果,适合处理较大的N值:
算法步骤
给定当前符合条件的数x,下一个数的计算逻辑:
s = x + 1:找到第一个可进位的位置,触发低位翻转c = x & -x:提取x的最低位1(利用补码特性)r = x + c:将最低位1及其右侧的0全部翻转,得到进位后的基础值mask = (s ^ r) >> 2:计算需要调整的右侧位掩码next_x = r | (mask / c):将右侧位调整为最小的无相邻1形式,得到下一个符合条件的数
当next_x超过2^N时,停止迭代。
代码示例(C语言)
#include <stdio.h> #include <stdint.h> // 打印N位二进制字符串辅助函数 void print_binary(uint64_t x, int n) { char buf[65] = {0}; for (int i = n-1; i >= 0; i--) { buf[n-1 - i] = (x >> i) & 1 ? '1' : '0'; } printf("%s\n", buf); } void enumerate_no_adjacent_ones(int n) { uint64_t max = 1ULL << n; uint64_t x = 0; do { print_binary(x, n); // 计算下一个数 uint64_t s = x + 1; uint64_t c = x & -x; uint64_t r = x + c; uint64_t mask = (s ^ r) >> 2; x = r | (mask / c); } while (x < max); } int main() { puts("N=4时的符合条件位向量:"); enumerate_no_adjacent_ones(4); return 0; }
输出验证(N=4)
运行代码后会输出:
0000 0001 0010 0100 0101 1000 1001 1010
所有结果均无相邻置位,符合要求。
复杂度说明
每次生成下一个数的操作都是O(1)的位运算,总共有F(N+2)个符合条件的数。由于斐波那契数列的增长速度是φN(φ≈1.618),远慢于2N,因此该方法的效率远高于朴素筛选法。
内容的提问来源于stack exchange,提问作者ynn
相关产品推荐
相关产品推荐

