题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
知识点
进制转换,位运算
Qiang的思路
第一次看到这个问题,感觉考察的是进制转换,所以想到的思路就是先将整数转化为二进制,此时是绝对值的原码,然后需要判断原来的数是不是正数,如果不是则需要进行一系列操作,包括:将第一位改为1得到原码,然后转化为反码,就是除了第一位所有的位置均取反,然后在加一,保持符号位不变。这样就得到了整数的二进制补码。最后通过遍历补码序列,对其中的1进行计数,得到的就是题目要求的二进制中1的个数。
# -*- coding:utf-8 -*-
class Solution:
def binary(self, n, length):
b=[]
while n!=0:
b.insert(0, n%2)
n=int(n/2)
for i in range(length-len(b)):
b.insert(0, 0)
return b
def symbol_binary(self, b, symbol, length):
if symbol==True:
return b
flag=True
for i in range(length-1, -1, -1):
b[i]=1-b[i]
if flag==True:
b[i]=0 if b[i]==1 else 1
flag=False if b[i]==1 else True
else:
flag=False
b[0]=1
return b
def NumberOf1(self, n):
# write code here
if n==0:
return 0
symbol=True if n>0 else False
n=n if n>0 else -n
b=self.binary(n, 32)
symbol_b=self.symbol_binary(b, symbol, 32)
count=0
for i in symbol_b:
count+=i
return count
这个代码中,binary方法是求绝对值的原码方法,symbol_binary方法的功能是求整数的补码。对于这种做法来说,我们需要提前知道一个问题,就是系统中存储整数用了多少个字节。对应着代码中的两个数字,通过测试得到系统将整数用四个字节进行存储,也就是32位。同样,也是通过这个问题,我感觉应该可以不这样做,因为题目中没有给出整数用多少字节存储,也没有说明整数的最大值和最小值。
Book中思路V1
书中给出的做法是位运算。因为整数本身在内存中是以补码的形式存储的。
简单的做法就是用1和整数做与运算,判断最低位是不是1,然后1左移,在做与运算判断次低位是不是1,反复下去,对整数的每一个位都进行判断,最后将所有为1的位置计数得到1的个数。对于C/C++而言,因为整数在内存中存储的位数可以通过1左移到0的时候反映出来,所以无需关系整数在系统的存储所占的位数。但是对于Python,因为Python的整数位数可以无限多,所以需要提前知道系统需要多少位存储这个整数才可以确定终止条件。
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1(self, n):
# write code here
result=0
one=1
for i in range(32):
if n&one!=0:
result+=1
one=one<<1
return result
Book中思路V2
第二种做法是通过分析发现将n减一之后和n做与运算的结果是将n的最后一个1去除了,按照这个思路做多次与运算直到n为0时,与运算的次数就是1的个数。但是同样在Python中,因为整数位数可以无限,所以对于正数来说这个理论是成立的,但是对于负数并不行。所以在这里我分了正数和负数两种情况进行了实现。正数的情况就采用这个思路。负数的情况采用上面的思路,总体上可以降低时间开销。
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1(self, n):
# write code here
result=0
if n>=0:
while n!=0:
result+=1
n=(n-1)&n
else:
one=1
for i in range(32):
if n&one!=0:
result+=1
one=one<<1
return result
作者原创,如需转载及其他问题请邮箱联系:lwqiang_chn@163.com。
个人网站:https://www.myqiang.top。
网友评论