Pra*_*are 11 python algorithm discrete-mathematics
如何在没有实际转换和计数的情况下获得数字的二进制表示中的"1"的数量?
例如
def number_of_ones(n):
# do something
# I want to MAKE this FASTER (computationally less complex).
c = 0
while n:
c += n%2
n /= 2
return c
>>> number_of_ones(5)
2
>>> number_of_ones(4)
1
Run Code Online (Sandbox Code Playgroud)
我不是一个python程序员,但希望你能够遵循它.
c = 0
while n:
c += 1
n &= n - 1
return c
Run Code Online (Sandbox Code Playgroud)
虽然有点模糊,但它的主要优点是速度和简单性.对于n中设置为1的每个位,while循环仅迭代一次.
你不能使这个计算上不那么复杂.它将是O(n)的位数,或者,如同&技巧的答案所示,O(n)的位数设置为1; 但除非您使用的所有数字都是特殊情况,后者平均应为n/2,因此这两个O(n)数字都是相同的.
当然,查找表技巧实际上对计算复杂性没有任何作用; 它只是用空间来支付时间,但没有改变基础经济学,你必须以某种方式检查每一位,而且没有办法解决这个问题.从逻辑上讲,您无法在不检查每个位的情况下回答有关数字位的问题.
现在,我想我有点草率,因为这些例子实际上是O(n ^ 2),因为在Python中你必须一次检查整数,所以使用Python长整数,比方说,100字节,一个+或一个&或一个/操作将至少查看一次每个字节,这将一遍又一遍地发生,直到数字减少到零(在上面概述的方案中),所以这些实际上也是O( n ^ 2)操作.我不确定Python会在这里允许真正的O(n)解决方案.
无论如何:如果你真的在询问计算复杂性,这特别意味着大O分析,那就是你的答案.:-)
IMO,一个好的方法是使用一个查找表 - 创建一个字典,将字节转换为1的数字(你可以使用你发布的代码生成它,它只需要运行一次),然后使用一些东西像这样:
def number_of_ones(n):
sum = 0
while n != 0:
sum += lookup_table[n & 0xff]
n >>= 8
return sum
Run Code Online (Sandbox Code Playgroud)
我相信这在空间和运行时间之间是一个相当不错的权衡.