首页 > 代码库 > 剑指Offer:二进制中1的个数

剑指Offer:二进制中1的个数

题目:输入一个整数,输出该数二进制表示中1的个数。

// 二进制中1的个数#include <stdio.h>int wrong_count_1_bits(int n) // 错误解法: 当n为负数时, n>>=1右移, 最高位补1, 陷入死循环{    int count = 0;    while(n)    {        if( n & 1 )            ++count;        n >>= 1;    }    return count;}int count_1_bits(int n) // 常规解法, 若sizeof(int)=4, 循环32次{    unsigned int mask = 1;    int count = 0;    while(mask) // 循环32次后, mask变为0    {        if( mask & n )            ++count;        mask <<= 1;    }    return count;}int perfect_count_1_bits(int n) // 高效解法, 若n含二进制位为1的位数为t, 则循环t次{    int count = 0;    while(n)    {        n = (n-1) & n; // 执行该语句后, n的二进制表示中, 最右边的1被置为0, 其余各位不变, 也即是每循环一次, 消去n最靠右的1        ++count;    }    return count;}int static_table_count_1_bits(int n) // 静态表法{    int table[16] =    {        0, 1, 1, 2,        1, 2, 2, 3,        1, 2, 2, 3,        2, 3, 3, 4    };    int count =0 ;    while (n)    {        count += table[n &0xf] ;        n >>=4 ;    }    return count ;}int main(void){    printf("sizeof(int)=%d\n",sizeof(int));    printf("%d\n",0x0fffff73); // 非负数正常; 负数(如0xffffff73)会导致程序在wrong_count_1_bits函数处陷入死循环    int count1 = count_1_bits(0x0fffff73);    int count2 = perfect_count_1_bits(0x0fffff73);    int count3 = wrong_count_1_bits(0x0fffff73);    int count4 = static_table_count_1_bits(0x0fffff73);    printf("count1=%d,count2=%d,count3=%d,count4=%d\n",count1,count2,count3,count4);    return 0;}

 

关键点:把一个整数减去1之后再和原来的整数做按位与运算& ,得到的结果相当于把整数的二进制表示中的最右边一个1变成0。

 

相关题目1:用一条语句判断一个整数是不是2的整数次方

if( (n-1)&n == 0 ) printf("Yes\n");

 

相关题目2:输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。

步骤1:求这两个数的异或 t = m^n;

步骤2:统计异或结果t的二进制表示中1的个数,即为需要改变的位数。

 

相关题目3:二进制中0的个数

方法1:上面常规解法中,改成 if( n^mask == 1 )  ++count;

方法2:先使用上面某种方法求得“二进制中1的个数”,间接求解:sizeof(int)*8 - 1的个数