C 如何找到1';在O(1)时间内,二进制数是多少?

C 如何找到1';在O(1)时间内,二进制数是多少?,c,algorithm,bit-manipulation,C,Algorithm,Bit Manipulation,我知道以前有人问过这个问题,但我正在查看下面列出的特定解决方案: 它是如何工作的 这里有什么警告吗 从理论上讲,有可能在恒定的时间内找到答案吗?我的意思是,我们不是真的需要迭代位来计数吗?迭代位的时间是恒定的,因为类型中的位数是恒定的。 因此,检查一位掩码并为目标值中的每一位移位的解决方案实际上是O(1)(例如,常数为32)。实现这一点的最快方法是popcnt指令。您通常可以通过以下方式访问它。您的解决方案在缺少此指令的平台上很有用。计算位 无符号32位整数u可以这样编写: u=a31*231+

我知道以前有人问过这个问题,但我正在查看下面列出的特定解决方案:

它是如何工作的

这里有什么警告吗

从理论上讲,有可能在恒定的时间内找到答案吗?我的意思是,我们不是真的需要迭代位来计数吗?

迭代位的时间是恒定的,因为类型中的位数是恒定的。
因此,检查一位掩码并为目标值中的每一位移位的解决方案实际上是
O(1)
(例如,常数为32)。

实现这一点的最快方法是popcnt指令。您通常可以通过以下方式访问它。您的解决方案在缺少此指令的平台上很有用。

计算位 无符号32位整数
u
可以这样编写:

u=a31*231+a30*230+…+a0*20

我们需要
a31+a30+…+的值a0

让我们比较一下
u>>k
的值:

u >> 0 = a31 * 231 + a30 * 230 + ... + a1 * 21 + a0 * 20 u >> 1 = a31 * 230 + a30 * 229 + ... + a1 * 20 u >> 2 = a31 * 229 + a30 * 228 + ... ... u >> 29 = a31 * 22 + a29 * 21 + ... u >> 30 = a31 * 21 + a30 * 20 u >> 31 = a31 * 20 让我们来看看为什么会这样:

  u >> 0 - u >> 1 - u >> 2 - ... - u >> 31
= u >> 0 - (u >> 1 + u >> 2 + ... + u >> 31)
= u - q
q
的值是多少?让我们一点一点地计算它,看看上面
u>>k
的值。对于
a31
,它是:

a31 * 230 + a31 * 229 + ... = a31 * (230 + 229 + ...) = a31 * (231 - 1) 根据上述算法,取两者之差,
uCount
中的每个八位字节包含
u
中相应八位字节中设置的位数

uCount      =   αβγδεζηθικλ (each greek letter is an octet)
uCount >> 3 =    αβγδεζηθικ
所以
uCount+(uCount>>3)
(λ+κ)*20+(κ+ι)*23+(ι+θ)*26+…

通过与
0O3070707
进行ANDing运算,我们屏蔽了每一个八位组,因此我们只对每一对进行一次计数:

r = (λ+κ) * 20 + (ι+θ) * 26 + (η+ζ) * 212 + ... = (λ+κ) * 640 + (ι+θ) * 641 + (η+ζ) * 642 + ... r=(λ+κ)*20+(ι+θ)*26+(η+ζ)*212+。。。 = (λ+κ) * 640 + (ι+θ) * 641 + (η+ζ) * 642 + ... 这是一个以64为基数的数字,我们想把以64为基数的数字相加,得到α+β+γ+δ+ε+ζ+η+θ+ι+κ+λ,我们的最终结果。要做到这一点,我们计算它的基数64:知道结果永远不会大于32,我们只需将数字乘以63。

展示了如何做到这一点。该方法可用于8位、16位、32位、64位、128位等字,但计算中使用的常数会发生变化

当我们说这个运算是O(1)时,我们的意思是它可以在恒定的时间内完成,而不管字长如何。用简单的方法计算位的数量是O(n)

实际上,当处理器能够以本机方式处理字大小时,这仅仅是O(1)


至于它是如何工作的,它使用了“幻数”。请参阅以获得解释。

除非你处理的是多精度数字,否则迭代位是常数时间——常数是整数的位数。从技术上讲,无符号整数是4个字节,如果你总是迭代整数中的所有32位,而不考虑N,那么从技术上讲,它是O(1)。请记住,O(1)表示时间复杂度不随N的值而改变。注意,这仅适用于32位输入(无符号整数)。因此,输入是已知的,且长度恒定,因此一些奇特的位算法可以给出答案。如果是非常数长度,则迭代几乎是不可避免的。请注意,如果N没有上界,则算法必须是O(logn)。虽然这是一个有趣且可能有指导意义的解决方案,但非二次幂的模通常比多个备选方案(例如或多个表查找)更慢(通常是256个条目的表格)。我没有投反对票,你的答案是对的,但我认为他指的是有效时间,而不是O(1)复杂度。这个问题的措辞确实很糟糕,但他似乎只是想了解如何在没有循环的情况下实现这一点。我想说,O(1)时间意味着省去了循环通过位数的解决方案(即O(n)时间)包括低级的解决方案或例程,因此我认为它是只使用二进制算术作为一个整体,而不是每一位的解决方案。顺便提一下,我想问完全相同的问题,但要找到(最重要的)设置位(即)的位置否决票,有什么可以分享的吗?通常会提供否决票的理由。 a30 * 229 + a30 * 228 + ... = a30 * (229 + 228 + ...) = a30 * (230 - 1) u - q = a31 * 231 - a31 * (231 - 1) + ... = a31 + a30 + ... + a0
u >> 0                = AaBbbCccDddEeeFffGggHhhIiiJjjKkk (each letter is a bit)
u >> 1 & 033333333333 =  A Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk (blank = zero)
u >> 2 & 011111111111 =     B  C  D  E  F  G  H  I  J  K
uCount      =   αβγδεζηθικλ (each greek letter is an octet)
uCount >> 3 =    αβγδεζηθικ
r = (λ+κ) * 20 + (ι+θ) * 26 + (η+ζ) * 212 + ... = (λ+κ) * 640 + (ι+θ) * 641 + (η+ζ) * 642 + ...