题目描述
输入一个整数,输出该数二进制表示中 1 的个数。其中负数用补码表示。
考察二进制和位运算。
解题思路
代码一:
1. 判断整数二进制最右边一位是不是1,然后整体向右移一位,最前面补0,直至整个整数为0。
2. 例如整数10的二进制为0000 0000 0000 0000 0000 0000 0000 1010(Java的int类型占用4个字节,即32位)。只看后四位的话,右移一位变成0101,继续右移为0010、0001、0000,可见右移三次整数就变成0。若右移过程中最后一位为1,则记录下来。
3. 至于如何判断最后一位是否为1,可以把整数和1进行与操作判断结果是否为1即可。
4. 缺点:如果整数是负数,则代码一会报错,因为在对负数进行右移运算时,补的是1,这样会导致死循环。
代码二:
1. 优化:让整数和1进行与运算,判断整数的末位是否为1;让1左移,判断倒数第二位是否为1…。例如给定整数10,二进制为1010,和1即二进制0001进行与操作,结果不为1;让1左移一位,即0001变为0010,再和1与操作,结果为1,记录下来…。
2. 缺点:整数的二进制有多少个1就要循环多少次。
代码三:
1. 若整数的二进制最后一位为1,减1后最后一位变成0。例如1001 - 0001 = 1000。
2. 若整数的二进制最后一位不为1,最后那个1是第n位,则减1后第n位的1变成0,之后的0都变为1,之前的不变。例如1100,最右边的1在第2位,减1后:1100 - 0001 = 1011。
3. 总结:把整数减1,就是将整数的二进制最右边那个1之后的0都变成1。
4. 接着将整数和减1的结果做与运算,作用是将第n位后的1都变成0。例如1100减1后为1011,将1100和1011与运算后为1000。
5. 继续使用减1,与运算之后的数进行循环,直至整数变为0。
6. 优点:整数的二进制有多少位1就运行多少次。
代码
// 代码一
public int NumberOf(int n) {
int count = 0;
while(n != 0){
if((n & 1) == 1){
count++;
}
count = count >> 1;
}
return count;
}
// 代码二
public int NumberOf(int n) {
int count = 0;
int flag = 1;
while(flag != 0){
if((n & flag) != 0){
count++;
}
flag = flag << 1;
}
return count;
}
// 代码三
public int NumberOf(int n) {
int count = 0;
while(n != 0){
count++;
n = (n - 1) & n;
}
return count;
}
文章汇总见这里 >>剑指Offer汇总<<
更多精彩文章见这里 >>我的学习小站<< & 更多好玩见这里 >>技术杂谈<<