输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
看到这个题目,就应该想到,这样的题目需要用位运算来解决,这才是正确的门,要是没想到用位运算,那就是还没入门。
思路一:
既然是位运算,那可不可以直接用1与输入n进行&位运算,结果为1的话,个数加一,否则个数不变,之后n向右位移1。
这样做是不行的,本题给出的整数是有符号的,对于正数可以这样操作,但对于负数来说,向右移位是补1的,那岂不是1的个数越补越多,停不下来了?
思路二:
既然思路一不通,那我直接用1与n做&位运算,结果为1的话,个数加一,否则个数不变,之后“1”这个变量向左位移1,这样就解决了思路一的困惑:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class
Solution {
public
:
int
NumberOf1(
int
n) {
int
flag=1;
int
count=0;
while
(flag!=0)
{
if
((n & flag)!=0)
count ++;
flag= flag<<1;
}
return
count;
}
};
|
事实证明这种方法是ok的。
思路三:
注明:思路三是从牛客网看来得,有大神想出的神来之笔:
链接:https://www.nowcoder.com/questionTerminal/8ee967e43c2c4ec193b040ea7fbb10b8
来源:牛客网
public
static
int
NumberOf1(
int
n) {
int
count =
0
;
while
(n !=
0
) {
++count;
n = (n -
1
) & n;
}
return
count;
}
这个方法巧妙之处在于,每次做完 (n-1)& n的运算后,二进制n的最右面的1都会被转化为0,这个可以拿起笔推算一下,亲测有效。