question:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
本题需要知道的一点是:一个整数也就是int类型,4个字节,一个字节有8位,所以一共就有32位
resolution1:
该方法的思路是一种比较容易想到的思路。要统计一个32位的二进制数中1的个数,那么就可以依次遍历这32位数,判断为1 还是 0
那么如何遍历呢?这里就要借助Java的toBinaryString()方法将十进制数转为二进制数(当然这种直接调用库函数的方法在面试中就不要用了,毕竟不是出题人的意图,如果是应付笔试的话当然是怎么简单怎么来了)
public int NumberOf1(int n) {
String bs = Integer.toBinaryString(n);
int count = 0;
for(int i = 0; i< bs.length(); i++){
if(bs.charAt(i) == '1'){
count++;
}
}
return count;
}
resolution2:
- 该方法也是在方法一的基础上来的,只是这里的遍历借助了移位的思想,依次将32位数向右移动,直到将首位移动到最后一位
- 其次,这里的每移动一位相与是指将最后一位和二进制的1进行相与,相当于吐弹珠,吐一个对比一个
- 由于考虑到负数的情况,这里采用的是无符号右移<<<,即向右移多少位,就在前面添加多少个0;这里不采用符号符号右移<<的原因是负数有符号右移时,右移多少位,就在前面添加多少个1。
- 而此题我们讨论的是统计1的个数,所以如果采用有符号右移,那么右移多少位,前面又会补多少个1,所以就是一个死循环了
public int NumberOf1(int n) {
int count = 0;
for(int i = 0; i < 32; i++){
if((n >>> i & 1) == 1){
++count;}
}
return count;
}
resolution3:
- 该方法的精妙之处在于利用了这样一个性质:两个相邻的二进制数n、n-1 相与,其结果中1的个数 = n中1的个数 - 1;那么就可以依次递归,直到n为0,那么肯定就不包含1了。
public int NumberOf1(int n) {
int count = 0;
while(n!= 0){
count++;
n = n & (n - 1);
}
return count;
}
附上一个例子当n=5时的情况:
****************
101==>n:5
100==>n-1:4
100==>n & n-1:4
count:1
****************
100==>n:4
11==>n-1:3
0==>n & n-1:0
count:2
2