【问题标题】:An algorithm using bit flips to iterate over all numbers with k bits一种使用位翻转来迭代所有具有 k 位的数字的算法
【发布时间】:2017-04-15 00:23:11
【问题描述】:

我正在寻找一种有效的方法来遍历所有 n 位非负整数,这些整数通过一次翻转一位来设置最多 k 位。

我需要做的最少位翻转次数是多少 迭代所有 n 位非负整数,最多设置 k 位?

我知道如果 k = n,即我们想要遍历所有 n 位非负整数,那么我们可以使用 Gray code。这有一个很好的特性,即您只需更改一位即可获得一个新数字。然而,如果 k

【问题讨论】:

    标签: algorithm math gray-code


    【解决方案1】:

    遍历位 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 的位数?
    • 理想情况下,我也只需更改一位即可获得格雷码中的新数字。
    • @Arthur:迭代具有固定数量的 1 位的值需要将至少 2 位从一个值更改为下一个值。你不能通过每次只改变 1 位来做到这一点。
    • @AnT 一次更改 2 个对我来说也很好。当然,如果我们取消对最多设置 k 位的限制,则可以使用格雷码迭代所有 n 位非负数一次更改一位。
    • @Arthur:嗯,这是您在external 规范级别可以/需要做什么的问题。如果您的算法的外部行为应该看起来像您正在迭代恰好具有 k 1 位的值,那么在后台使用格雷码不会看起来您每次只翻转 1 位。
    【解决方案2】:

    一种已知的位摆弄技术可以如下实现(使用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。)

    【讨论】:

    • 这很好。但是,在我的情况下,我真的想尽可能少地翻转。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-15
    • 1970-01-01
    • 2015-06-30
    • 1970-01-01
    • 2020-04-28
    • 2019-12-04
    • 1970-01-01
    相关资源
    最近更新 更多