在线题目链接:二进制中1的个数
文章目录
- 1 题目描述
- 2 题目分析
- 2.1 方法1
- 2.11 Java代码
- 2.12 C++代码
- 2.2 方法2
- 2.21 Java代码
- 2.22 C++代码
- 3 总结
1 题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
2 题目分析
2.1 方法1
这道题看起来很简单。假设输入的整数是n。
只需要将n与1进行相与运算,看结果是不是0,然后再将n右移,再循环上述步骤直到n=0为止。看起来是这样,但是这样做存在一定的问题。
题目中明确说出n可能为负数,如果将负数右移,那么高位会被符号1填充,这就导致结果不正确。不过在java中,可以使用“>>>”进行无符号右移。
在C++中不能进行无符号右移,所以我们就干脆不右移,而是左移。左移的话不会产生因为符号而不同的结果。具体的做法可以让n与1相与,然后让1左移,然后重复让n与左移后的1相与…
2.11 Java代码
常规的左移相与操作
public class Solution {public int NumberOf1(int n) {int cnt = 0;int flag = 1;while(flag!=0){if((n&flag)!=0)cnt++;flag=flag<<1;}return cnt;}
}
下面是使用java的无符号右移“>>>”
public class Solution {public int NumberOf1(int n) {int cnt = 0;while(n!=0){if((n&1)!=0)cnt++;n=n>>>1; //java没有unsigned关键字,>>>就是java中的无符号右移}return cnt;}
}
2.12 C++代码
class Solution {
public:int NumberOf1(int n) {int cnt = 0;unsigned int flag = 1;while(flag){if(n & flag)cnt++; //不管n是不是负数,都成立flag=flag<<1;}return cnt;}
};
2.2 方法2
方法1比较常规。还有更加高效的方法。
根据下面的原理:
- 把一个整数减去1,再和原来的整数做相与运算,会把该整数二进制的最右边的1变成0。
那么根据上述的原理,一个整数中有多少个1,就可以进行多少次上述的相与运算。根据这种思路,可以写出更加高效的算法。
2.21 Java代码
public class Solution {public int NumberOf1(int n) {int cnt = 0;while(n!=0){cnt++;n=n&(n-1);}return cnt;}
}
2.22 C++代码
class Solution {
public:int NumberOf1(int n) {//把一个整数减去1,再与原整数相与,会把原整数的最右边的1变成0int cnt = 0;while(n){cnt++;n=n&(n-1);}return cnt;}
};
3 总结
注意位运算的思路。位运算一般具有发散思维,比较难想。
探讨学习加:
个人qq:1126137994
个人微信:liu1126137994