【发布时间】:2017-04-15 00:23:11
【问题描述】:
我正在寻找一种有效的方法来遍历所有 n 位非负整数,这些整数通过一次翻转一位来设置最多 k 位。
我需要做的最少位翻转次数是多少 迭代所有 n 位非负整数,最多设置 k 位?
我知道如果 k = n,即我们想要遍历所有 n 位非负整数,那么我们可以使用 Gray code。这有一个很好的特性,即您只需更改一位即可获得一个新数字。然而,如果 k
【问题讨论】:
我正在寻找一种有效的方法来遍历所有 n 位非负整数,这些整数通过一次翻转一位来设置最多 k 位。
我需要做的最少位翻转次数是多少 迭代所有 n 位非负整数,最多设置 k 位?
我知道如果 k = n,即我们想要遍历所有 n 位非负整数,那么我们可以使用 Gray code。这有一个很好的特性,即您只需更改一位即可获得一个新数字。然而,如果 k
【问题讨论】:
遍历位 0 的所有值:从任何起始值开始,然后翻转位 0。
遍历位 0、1 的所有值:从任何起始值开始。迭代位 0 的所有值。翻转位 1。迭代位 0 的所有值。
遍历位 0-2 的所有值:从任何起始值开始。迭代位 0、1 的所有值。翻转位 2。迭代位 0、1 的所有值。
遍历位 0-3 的所有值:从任何起始值开始。遍历位 0-2 的所有值。翻转位 3。迭代位 0-2 的所有值。我希望系统现在很清楚。
从 i = 任何值开始,j = 0。 j 加 1,确定 j 中设置的最低位,翻转 i 中的那个位。冲洗并重复。
【讨论】:
k 1 位的值,那么在后台使用格雷码不会看起来您每次只翻转 1 位。
一种已知的位摆弄技术可以如下实现(使用unsigned 是底层的 n 位整数类型)
unsigned next_combination(unsigned x)
{
unsigned u = x & -x;
unsigned v = u + x;
x = v + (((v ^ x) / u) >> 2);
return x;
}
它在一些具有相同 1 位数的整数序列中生成“下一个”数字。 (1u << k) - 1u 是起点。当第一次溢出发生时,迭代结束。后者意味着该算法可以立即用于n小于unsigned中的位数。
(有关更详细的说明,请参阅https://en.wikipedia.org/wiki/Combinatorial_number_system。)
【讨论】: