剑指offer:二进制中1的个数
(1) 运用Python函数
代码详细:
1 | def numberOf1(n): |
或者:1
2def numberOf1(n):
return bin(n & 0xffffffff).count('1')
这里bin
函数将数字转换为二进制,count
为Python内置函数,计算1的个数
(2) 基础数据类型
1 | def countOnes(x): |
or1
2
3
4
5
6
7# 负数
def countOnes(x):
count = 0
while x&0xffffffff != 0:
count += 1
x &= (x-1)
return count
补充
Python中为什么可以通过bin(n & 0xffffffff)来获得负数的补码?
python通过bin(n & 0xffffffff)获得的并不是这个负数的补码,只是形式与负数的32位二进制补码相同罢了。
举个例子:1
2n = -3
n = n & 0xffffffff #n=4294967293
bin(n)
查看二进制形式:'0b11111111111111111111111111111101'
由于python中没有位数这一概念
所以python认为'0b11111111111111111111111111111101'
是正数。
不要看它首位是1。
你看1和-1的二进制表示:1
2bin(1)#'0b1'
bin(-1)#'-0b1'
所以二进制中1的个数的题目利用了这个技巧,将负数转化为正数,而它们的二进制形式是相同的,而对正数的二进制进行操作非常简单清晰,统计到这个正数二进制形式中1的个数就是原来负数的二进制形式中1的个数,这样就可以消除负数的影响。
python中,对于负数,无论是右移操作,还是n&(n-1)
操作,都会陷入死循环。右移操作是由于负数的最高位总要设为1,最终会变为0xffffffff
而陷入死循环。n&(n-1)操作,由于python没有位数概念,负数最左边的1不知道在第几位(觉得这是个坑,具体原理不太清楚),n&(n-1)
会不断将最右边的1变为0,也将陷入死循环。
Python3,当长度超过32位或64位之后,Python3会自动将其转为长整型,长整型理论上没有长度限制。