题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
public int NumberOf1(int n) {
if(n==0) {
return 0;
}
int count=0;
while(n!=0) {
count++;
n=n&(n-1);
}
return count;
}
此解法是我在牛客网评论中看到的,确实是我所理解中最优的解法,下面我来分析一下此最优解法:
首先当二进制是0的时候直接返回0,这个毋庸置疑;
很多人第一眼看见会问代码里面没有考虑到负数的二进制情况(别急听我分析)
我们首先考虑正式,我们首先的情况所有的数不管是什么语言,其底层都是二进制编码,因为计算机只能读懂二进制.所以我们做题的时候根本不用考虑要不要将十进制转换成二进制的问题.
假设 n=22,那么它的二进制就是0001 0110 然后
进入循环-->
count=1,
n与(n-1)进行逻辑&运算-->0001 0110 & 0001 0101 -->0001 0100
(其实其本质就是从后面数1,数完一个1就把1拿掉,继续然后)
又进入循环-->
count=2,
n与(n-1)进行逻辑&运算-->0001 0100 & 0001 0011 -->0001 0000
又进入循环-->
count=3,
n与(n-1)进行逻辑&运算-->0001 0000 & 0000 1111 -->0000 0000
最后退出循环;
现在考虑负数,负数的话一共两步:
1.将负数先变成反码,
2.数它反码中1的个数,
第一步,操作系统已经帮我们做了,你觉得你还要干什么吗?
第二步,直接又是在二进制中数1的个数,不是一样的吗?难得正数的二进制和反码的二进制还有不同?
所以这题就这么简单的完美解决!