剑指offer系列——11.二进制中1的个数

Q:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
C:时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32M,其他语言64M
T:(不要用右移的方法做,要注意可能会有负数!!!)
第一种方法,整形数字在32系统占32位,由低位到高位,按位与1,即可统计出32位中1的个数。

     int  NumberOf1(int n) {
        int count = 0;
        for (int i = 0; i < 32; i++) {
            if (n & 1)
                count++;
            n >>= 1;
        }
        return count;
     }

第二种,这种方法hin神奇,通过二进制构数原理。
一个为n的数,在不为0的前提下,二进制至少有一个位数为1。设n二进制值总共有k位,n-1时,n最右边的1位设为i位,i位更改为0,i位右边(k-i)位的0位全部更改为1,i位左边(i-1)位所有位数不变。则n&(n-1)的值,1~(i-1)位同为1有m位,相与为1,有(i-1-m)位为0,相与为0;i~k位为相与位0,则n&(n-1)共有m位为1,n共有(m+1)位为1。
综上,n&(n-1)比n位数为1的个数少1.
流程图如下:(画的好丑……)

代码:

     int  NumberOf1(int n) {
         int count=0;
         while(n)
         {
             n=n&(n-1);
             count++;
         }
         return count;
     }

P.S. 我崩了两次……第一次是直接每位右移,但如果是负数,会导致进入死循环;

    int NumberOf11(int n) {
        int count = 0;
        while (n) { //如果输入为负数,n=-1,进入死循环
            if (n & 1)
                count++;
            n >>= 1;
        }
        return count;

第二次,既然如此,那就做n=-1的判断,但这种,如果是2的幂次方的负数,就会本身在-1处有一个1判断不到。

//例如输入-2,输出为1,但这个代码输出为0
    int NumberOf11(int n) {
        int count = 0;
        while (n && n != -1) {
            if (n & 1)
                count++;
            n >>= 1;
        }
        return count;
    }
原文地址:https://www.cnblogs.com/xym4869/p/12246183.html