第十题:二进制数中1的个数
题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
解析:正常想法是将target数进行位移运算,计算出target数中的1的个数,例:target=7,二进制表示:0111,怎样计算target二进制的1的个数呢?
将target二进制数与数字1进行与(&)运算,如果每次运算的结果等于1,那么target数的二进制数最右边就为1,可以定义一个变量count用来记录target二进制数中1的个数,并且每次讲target数进行向右位移一位,知道target=0为止。此时count记录着target二进制数中的1的个数。
如下图所示:(但是这仅仅是对于target为正数而言)
具体实现代码如下所示:
/**
* 功能描述: <br>
* 〈该函数计算二进制数中1的个数〉
* @return:int
* @since: 1.0.0
*/
public int method1(int num) {
int count = 0;
while(num != 0){
if((num & 1) == 1){
count++;
}
num = num >> 1;
}
return count;
}
当target为负数时会出现什么情况呢?
解析: 负数在计算机中是用补码表示的,最高位是1,在右移的过程中,高位都是用1来填补的,所以在执行代码时就会陷入就会造成程序的死循环状态
次时怎么解决target数为负数呢?这时我们不需要将target数进行向右位移,将数字1向左位移,直到target=0为止。
具体实现代码如下所示:
/**
* 功能描述: <br>
* 〈该函数计算二进制数中1的个数〉
* @return:int
* @since: 1.0.0
*/
public int method2(int num) {
int count = 0;
int flag = 1;
while (flag != 0){
if ((num & flag) == 1){
count++;
}
flag = flag << 1;
}
return count;
}
解析:看了解法2的代码,会发现效率比较低,while循环会做好多次,解法3是一种非常高效的解法, 把一个整数减去1之后再和原来的整数做按位与,得到的结果相当于是把整数的二进制表示中最右边的一个1变成0。
具体实现代码如下所示:
/**
* 功能描述: <br>
* 〈该函数计算二进制数中1的个数〉
* @return:int
* @since: 1.0.0
*/
public int method3(int num) {
int count = 0;
while (num != 0){
count++;
num = num & (num-1);
}
return count;
}
NowCoder(Online Coding, Please Click)