二进制中1的个数_牛客题霸_牛客网
题目描述:输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
数据范围:−2^31<=n<=2^31−1
即范围为:−2147483648<=n<=2147483647
1. 心路历程
1.1 模除(沿用辗转相除法)
首先我想到的是模除的方法,这沿用的是十进制通过辗转相除法转化为二进制,模除得到的余数是二进制数,整除得到的是商下一次辗转相除的被除数。
原本顺利通过测试用例,而提交的时候却没有通过,出现了如下所示的未通过测试例子。该值-2147483648其实是(signed)int能表示的最小值。
由此我对该用例进行了分析如下,
为什么这个例子没有通过呢?牛客题目中限制n是signed int 类型,表示一个类型带有正负号,然而负数进行模除,结果的正负号由左操作数决定,这样得到的结果可能会带有符号。有符号数在内存中存储和无符号数是有差别的。因此,n 必须是unsigned int 类型。
由于牛客题目中对 n 有限制,只能是 signed int 类型,我便在VS2022编译器上完成了这段代码的修改,刚刚没有通过的用例也过了。
此外针对前面的分析,我想到了一种办法,把n强制类型转换为unsigned int 类型,但没出来。原因在于强制类型转换的使用。
复习完后,开始一波操作……要先创立一个变量n1,进行操作,不要 这样直接敲。
小结:unsigned int 数据和 signed 数据在内存中存储结果不一样。
1.2 n & (n - 1)法
方法解析如图:
代码如下:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型
* @return int整型
*/
int NumberOf1(int n ) {
// write code here
int count = 0;//计数1
while(n){
count++;
n = n & (n - 1);
}
return count;
}
1.3 左移操作法
2. 总结
今天只做了这一道题,但是收获颇多,题目在精不在多。列位友友们若发现错误,可以及时评论留言或者私信我哦!