计算int 型数值在内存中二进制1的个数

来源:互联网 发布:php网站开发培训 编辑:程序博客网 时间:2024/06/02 02:27

今天在华为OJ上遇到这么一个题目,很简单,但是却总是得不到最好的成绩记录。因此比较了自己的程序、思路与别人的异同,发现还是有很大区别的,遂记录如下

题目——

输入一个int型整数,求该整数的二进制在内存中有多少个1。例如输入10,由于其二进制表示为1010,有两个1,因此输出2。

思路1

<span style="font-size:18px;">public static void main(String[] args)      {                    Scanner scanner = new Scanner(System.in);        int m = scanner.nextInt();         int num = 0;        while(m>0){        m&=(m-1);        num++;        }                }  </span><span style="font-size: 16pt;"> </span>

这是最常规的思路。直接利用移位去算,始终判断最后一位是不是1,然后计数。这也是我一开始所所想到的,但是,这种写法只得到了60分。



思路2

<span style="font-size:18px;">private static int count_ones(int a)     {        a = (a & 0x55555555) + ((a >> 1) & 0x55555555);        a = (a & 0x33333333) + ((a >> 2) & 0x33333333);        a = (a & 0x0f0f0f0f) + ((a >> 4) & 0x0f0f0f0f);        a = (a & 0x00ff00ff) + ((a >> 8) & 0x00ff00ff);        a = (a & 0x0000ffff) + ((a >> 16) & 0x0000ffff);        return a;    }</span><span style="font-size: 16pt;"></span>


这是我看别人拿了满分的答案。这种思路比较难想到。一开始我怎么都想不明白他是怎么想出来的。直到翻看书籍,碰巧在《编程之美》上有记载这个题目,并且给出了五种解法。其中有两种就是以上两种。

这道题的本质相当于求二进制数的 Hamming 权重,或者说是该二进制数与 0 的 Hamming 距离,这两个概念在信息论和编码理论中是相当有名的。在二进制的情况下,它们也经常被叫做 population count 或者 popcount 问题,比如 gcc 中就提供了一个内建函数:int __builtin_popcount (unsigned int x)   输出整型数二进制中 1 的个数。但是 GCC 的 __builtin_popcount 的实现主要是基于查表法做的,跟编程之美中解法 5 是一样的。Wikipedia 上的解法是基于分治法来做的,构造非常巧妙,通过有限次简单地算术运算就能求得结果,特别适合那些受存储空间限制的算法中使用。

此外,在这个博客里也有对编程之美里五种解法的详细分析,值得一读。http://blog.csdn.net/shijiemazhenda/article/details/6785674  









1 0