题目:输入一个整数,输出该数二进制表示中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的位数
剑指offer (10) 二进制中1的个数,布布扣,bubuko.com
时间: 2024-10-23 18:36:10