计算具有相同汉明权重的二进制数的所有排列的最快算法是啥?
Posted
技术标签:
【中文标题】计算具有相同汉明权重的二进制数的所有排列的最快算法是啥?【英文标题】:What is the fastest algorithm to computer all permutations of a binary number with same hamming weight?计算具有相同汉明权重的二进制数的所有排列的最快算法是什么? 【发布时间】:2015-03-01 14:00:12 【问题描述】:我想要一种算法来计算具有给定汉明权重的固定大小二进制数的所有排列。例如,如果汉明权重为 2,二进制大小为 4,则有以下输出:
0011
0110
0101
1100
1010
1001
此类组合的数量计算为 C(n,r)
在此示例中为 C(4,2)
,即 6。
请注意,您可以通过将数字从 0 增加到 2^n 并查看计数是否正常来解决此问题。但是,这不是一个快速的解决方案。 我正在考虑在 C++ 中使用 bitset 类解决问题,我需要增加 N。
我想补充一点,这个问题有一个明显的递归算法。由于堆栈溢出,这不是一个好的答案。我从 Gosper 的 hack 中得到了很好的回答。虽然,我需要扩展输入并且可能稍后使用 MPI 实现,但我需要一个可扩展的库。 Unsigned int 不够大,我更喜欢像 bitset 这样的可扩展且快速的库。该解决方案不适用于此处,而 bitset 库中没有添加。还有其他解决方案吗?
【问题讨论】:
【参考方案1】:您可以使用Gosper's Hack 实现“按字典顺序排列的下一个位排列”:
unsigned int v; // current permutation of bits
unsigned int w; // next permutation of bits
unsigned int t = v | (v - 1); // t gets v's least significant 0 bits set to 1
// Next set to 1 the most significant bit to change,
// set to 0 the least significant ones, and add the necessary 1 bits.
w = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
或者如果你没有ctz
(MSVC 上的_BitScanForward
),
unsigned int t = (v | (v - 1)) + 1;
w = t | ((((t & -t) / (v & -v)) >> 1) - 1);
【讨论】:
【参考方案2】:您可以通过以下方式生成它们:
首先,创建一个开头有 n - r 个零和结尾有 r 个零的向量(0011
for n = 4 和 r = 2)。
然后,重复以下过程:
-
找到最右边的一个,使得零位于它的左边。
如果没有这样的人,我们就完了。
将其向左移动(移动一个位置,即与零交换)。
将位于右侧的所有元素从它移到矢量的最末端。
例如,如果我们有
0110
,我们首先将最右边的可以移动到左边得到1010
,然后我们将所有的从它向右移动到向量的末尾,得到1001
.
这个解决方案的时间复杂度为O(C(n, r) * n)
。此解决方案的另一个特点:它按字典顺序生成元素。
【讨论】:
以上是关于计算具有相同汉明权重的二进制数的所有排列的最快算法是啥?的主要内容,如果未能解决你的问题,请参考以下文章