【问题标题】:What is a quick way to get the n'th integer > 0, that has at most k bits set?获得最多设置 k 位的第 n 个整数 > 0 的快速方法是什么?
【发布时间】:2016-06-23 16:41:35
【问题描述】:

我有一个系列,值大于 0,其中设置的位数不超过k

for instance, for `k = 2`

n    binary    value    bits_set
0    0000      0        0
1    0001      1        1
2    0010      2        1
3    0011      3        2
4    0100      4        1
5    0101      5        2
6    0110      6        2
7    1000      8        1
8    1001      9        2
9    1010      10       2
10   1100      14       2
... etc ...

对于给定的k 值,是否有一种计算效率高的方法可以找到系列中的第 n'th 项?

我所有的尝试都表现得很慢,我不知道如何有效地解决这个问题。

【问题讨论】:

  • “Nth number”是什么意思?有许多数最多设置 M 位。您正在寻找最小的吗?
  • 我的意思是索引器操作符,例如数组[n]。
  • 请编辑您的问题以包含该信息
  • 指定号码的条件。正如我所说,有许多数字满足条件。你在分类吗?数组跟什么有什么关系?
  • 不,最多需要设置 M 位。

标签: c# math bits


【解决方案1】:

我知道这个问题被标记为 C#,很抱歉用 Python 给出答案:

首先,我们将找到一种方法来计算在可用空间中具有特定位数的不同数字的数量。然后我们将找到一种对这些结果进行排序的方法。

将 f(b, s) 表示为在 b 集合中恰好有 s 位构造一个数的方式数。

这里有一个递归关系。满足 f(b, s) 的数要么是满足 f(b-1, s) 且前面为 0 的数,要么是满足 f(b-1, s-1) 且前面为 1 的数。因此 f(b, s) = f(b-1, s) + f(b-1, s-1)。

该表中有一些基本情况: f(b,0) 为 1 f(b,s) 为 1,其中 b = s

    10 9 8 7 6 5 4 3 2 1 0
24   . . . . . . . . . . 1
23   . . . . . . . . . . 1
22   . . . . . . . . . . 1
21   . . . . . . . . . . 1
20   . . . . . . . . . . 1
19   . . . . . . . . . . 1
18   . . . . . . . . . . 1
17   . . . . . . . . . . 1
16   . . . . . . . . . . 1
15   . . . . . . . . . . 1
14   . . . . . . . . . . 1
13   . . . . . . . . . . 1
12   . . . . . . . . . . 1
11   . . . . . . . . . . 1
10   1 . . . . . . . . . 1
 9   0 1 . . . . . . . . 1
 8   0 0 1 . . . . . . . 1
 7   0 0 0 1 . . . . . . 1
 6   0 0 0 0 1 . . . . . 1
 5   0 0 0 0 0 1 . . . . 1
 4   0 0 0 0 0 0 1 . . . 1
 3   0 0 0 0 0 0 0 1 . . 1
 2   0 0 0 0 0 0 0 0 1 . 1
 1   0 0 0 0 0 0 0 0 0 1 1

还可以建立表格 g(b, s),它表示有多少 b 位数字设置了 s 或更少的位。 g(b, s) = sum(i = 0 to s) f(b, i)

所以我们现在可以回答在 24 位中设置了 10 位的数字有多少的问题,即 f(24, 10) = 1961256,我们可以回答最多设置 10 位的数字有多少在 24 中,即 f(24, 10) + f(24, 9) + f(24, 8) ... + f(24, 1) + f(24, 0) = g(24, 10) = 4540386

但是,如果问题是要找到第 n 个数字,使得 24 位中最多有 10 个被设置,我们需要能够以有序的方式搜索这个空间。

首先请注意,任何第n位第一个1的数都大于任何第一个1在任何位晚于n的数。

这意味着我们可以找到每个数字的位置,只需设置一个位,后跟 z 个零。这必然大于 g(z, max(z,10))。我们可以在这里进行优化,并声明由于 10 位空间中的所有数字都是合格的(它们的设置不可能超过 10 位),那么对于所有 n

如果 n > 2^10 (=> z > 10),我们可以通过找到最大的 z_10 来搜索第一个设置位的位置,使得 g(z_10, 10)

否则,我们必须找到最大的 z_9 使得 g(z_9, 9)

在 Python 中:

class Memoize:
    def __init__(self, f):
        self.f = f
        self.memo = {}
    def __call__(self, *args):
        if not args in self.memo:
            self.memo[args] = self.f(*args)
        return self.memo[args]

def g(b, s):
    r = 0
    for i in range(0, s+1):
        r = r + f(b, i)
    return r

def f(b,s):
    if b == s:
        return 1
    if s == 0:
        return 1
    if b < s:
        return 0
    return f(b-1, s) + f(b-1, s-1)

def build(s, n, i):
    d = (24 - len(s))
    if n <= 2 ** i:
        return s + format(n, '0%db' % (d))
    for z in range(i, d+1):
        x = g(z, i)
        if x < n:
            continue
        if x == n:
            return s + format(2 ** z, '0%db' % (d))
        y = g(z-1, i)
        return build(s + format(1, '0%db' % (d-(z-1))),
                     n - y,
                     i - 1)

def solve(n):
    return build("", n-1, 10)

f = Memoize(f)
g = Memoize(g)

for n in range(1, 4540387):
    print("%07d: %s" % (n, solve(n)))

【讨论】:

  • 我真的看不懂python,请给我一个简单的方法来回答我的代码问题。
猜你喜欢
  • 2019-10-11
  • 2022-12-24
  • 2023-03-15
  • 1970-01-01
  • 2020-12-25
  • 2011-11-28
  • 2014-01-09
  • 1970-01-01
  • 2019-07-23
相关资源
最近更新 更多