首页 > 代码库 > 剑指offer (10) 二进制中1的个数

剑指offer (10) 二进制中1的个数

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

我们可能很快写下如下代码:

 1 int NumOf1InBinary(int n)
 2 {
 3     int count = 0;
 4     while (n != 0) {
 5         if (n & 1 ) {
 6             ++count;
 7         }
 8         n >> 1;  // bug!!!
 9     }
10     return count;
11 }

 第8行存在bug.

首先C/C++中数有无符号数和有符号数两种(我一直认为无符号数是个蛋疼的存在,滋生大量的bug)

左移运算时:这两种数都是在右边空位补0

右移运算时:无符号数是在 左边空位补0

                 有符号数是在 左边空位补 符号位,即 如果是正数,则补0,如果是负数,则补1

 

所以上述代码中,如果 输入负数,则 左边空位一直补1,导致死循环

 

二进制位运算中,有一个很重要的性质:

我们将一个数减1,其结果的二进制表示:原数的最右边的1变为0,其后均为1,其前保持相同 

例如:  a   =  0x10101000

         a-1 =  0x10100111

我们将 a 与 a-1 做 与运算,则结果 将舍弃掉 最右边1以及其后的数

1 int NumOf1InBinary(int n)
2 {
3     int count = 0;
4     while (n != 0) {
5         ++count;
6         n &= (n - 1);
7     }
8     return count;
9 }

 

扩展:

1. 用一条语句判断 一个数是不是 2的整数次方

分析:如果一个数是2的整数次方,那么其二进制表示中肯定只有一个1,根据前面的分析

 n & (n - 1) == 0

即可判断

 

2. 输入两个整数m和n,m需要改变多少位二进制才能得到n

比如 10 : 1010

       13:  1101

10需要改变3位

 

计算m需要改变多少位,其实就是 计算 m 和 n 的二进制表示中 有多少位是不同的

涉及到 二进制位的同与不同,我们应该立马联想到 位的异或运算:位相同结果为0,位不同结果为1

我们可以将 m 和 n 做异或运算,然后计算 异或结果中的 1的位数