二进制中1的个数
题目描述:
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
思路:
重要的有两点:
- 如果一个整数不为0,那么这个整数的二进制数至少有一位为1,如果我们把这个整数减1,那么原来在这个整数二进制形式的最右边的1就会变为0,原来在这个1后边的所有0都会变为1(如果1后面还有0的话) 其余所有位将不受到影响。
- 0xFFFFFFFF是什么?
因为int 为带符号类型,带符号类型最高为是符号位,又因为0xFFFFFFFF,也就是四个字节32 bits全是1, 符号位是1,所以这个数是负数。
内存中的数值为补码表示,所以0xFFFFFFFF是一个负数的补码。
负数从补码求原码:最高符号位不变,保持 1, 其余各位求反,末尾加1,也就是比如补码:0xFFFFFFFF,二进制为:11111111 11111111 11111111 11111111
-> 10000000 00000000 00000000 00000000
-> 10000000 00000000 00000000 00000001
原码首位表示符号位,其余位表示绝对值大小,所以,这个数是 -1
把一个整数减去1之后再和原来的整数做位与运算,得到的结果相当于把整数的二进制表示中最右边的1变成0,很多二进制的问题都可以用这种思路解。
但是负数使用补码表示的,对于负数,最高位为1,而负数在计算机是以补码存在的,往右移,符号位不变,符号位1往右移,
最终可能会出现全1的情况,导致死循环。与0xffffffff相与,就可以消除负数的影响
实现:
class Solution:
def NumberOf1(self, n):
# write code here
count = 0
if n < 0:
n = n & 0xffffffff
while n:
count += 1
n = (n-1) & n
return count