计算一个数字中的设置位数

时间:2016-09-02 22:18:55

标签: python algorithm bit-manipulation

问题陈述是:

编写一个有效的程序,以整数的二进制表示形式计算1的数量。

我发现了一个关于此问题here的帖子,其中概述了在log(n)时间内运行的多个解决方案,包括Brian Kernigan的算法和gcc __builtin_popcount()方法。

没有提到的一个解决方案是python方法:bin(n).count("1") 这也达到了同样的效果。此方法是否也在log n时间运行?

2 个答案:

答案 0 :(得分:6)

您正在将整数转换为字符串,这意味着它必须生成N #include<stdio.h> int main(){ int n1,n2,n3,n4,n5; printf("Please enter the cost of the car then your down payment\n"); scanf("%d%d",&n1,&n2); n3=n1-n2; printf("Now enter how many months of financing you would like\n"); scanf("%d",&n4); n5=n3*1.05/n4; printf("Your car payment is %d per month",n5); return 0; } '0'个字符。然后使用必须访问字符串中每个字符'1'来计算str.count()个字符。

总而言之,你有一个O(N)算法,其成本相对较高。

请注意,这与您链接的代码具有相同的复杂性;整数'1'具有log(n)位,但算法仍需要进行N = log(n)步骤来计算位数。因此n算法是等效的,但,因为首先产生字符串的成本很高。

以表为代价,您可以转移到每个字节处理整数

bin(n).count('1')

但是,由于Python需要生成一系列新对象(一个table = [0] while len(table) < 256: table += [t + 1 for t in table] length = sum(map(table.__getitem__, n.to_bytes(n.bit_length() // 8 + 1, 'little'))) 对象和几个整数),因此这种方法的速度不足以超越bytes方法:

bin(n).count('1')

无论测试号码的位长度如何,>>> from random import choice >>> import timeit >>> table = [0] >>> while len(table) < 256: ... table += [t + 1 for t in table] ... >>> def perbyte(n): return sum(map(table.__getitem__, n.to_bytes(n.bit_length() // 8 + 1, 'little'))) ... >>> def strcount(n): return bin(n).count('1') ... >>> n = int(''.join([choice('01') for _ in range(2 ** 16)])) >>> for f in (strcount, perbyte): ... print(f.__name__, timeit.timeit('f(n)', 'from __main__ import f, n', number=1000)) ... strcount 1.11822146497434 perbyte 1.4401431040023454 总是慢一个百分点。

答案 1 :(得分:4)

假设您正在尝试计算n的设置位数。在 Python 典型实现中,bin将在O(log n)时间内计算二进制表示,count将遍历字符串,从而导致整体{{1}复杂性。

但是,请注意,通常,算法的输入参数是输入的“大小”。使用整数时,这对应于它们的对数。这就是为什么当前算法具有线性复杂度(变量为O(log n),复杂度为m = log n)。