问题:
对于任意的非负整数,统计其二进制展开中数位1的总数。
解决:
相关Blog:http://www.cnblogs.com/maples7/p/4324844.html
在看这篇之前可以先看看上述这篇,这篇主要讨论其优化问题。
常规解法:
O(logn):
1 int countOnes(unsigned int n) 2 { 3 int ones = 0; 4 while (0 < n) 5 { 6 ones += (1 & n); 7 n >>= 1; 8 } 9 return ones; 10 }
无非就是每次取其二进制展开最后一位,是1就计数。
效率由位运算可知(右移一位等价于除以2),为 O(logn)。
优化解法1:
O(countOnes(n)):
1 int countOnes1(unsigned int n) 2 { 3 int ones = 0; 4 while (0 < n) 5 { 6 ones++; // 计数(最后至少有一位为1) 7 n &= n - 1; // 清楚当前最靠右的1 8 } 9 return ones; 10 }
解释如下:
优化解法2:
O(logW), W = O(logn) 为整数的位宽, 实际上就是 O(1) 的算法。
代码及解释:
这个算法是一种合并计数器的策略。把输入数的32Bit当作32个计数器,代表每一位的1个数。然后合并相邻的2个“计数器”,使i成为16个计数器,每个计数器的值就是这2个Bit的1的个数;继续合并相邻的2个“计数器“,使i成为8个计数器,每个计数器的值就是4个Bit的1的个数。。依次类推,直到将i变成一个计数器,那么它的值就是32Bit的i中值为1的Bit的个数。
From : 《数据结构习题解析》,邓俊辉
Reference:
1、http://blog.chinaunix.net/uid-21275705-id-224360.html
2、http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
时间: 2024-10-06 22:05:21