剑指 Offer 15. 二进制中1的个数
题目描述:
请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。
示例:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。
# good trick
class Solution:
def hammingWeight(self, n: int) -> int:
return bin(x).count('1') # bin(n)返回的类型是字符型。采用str.count('1')进行计数即可。
1.Python中的整型是补码形式存储的
bin(-1)
'-0b1'
2.Python中bin一个负数(十进制表示),输出的是它的原码的二进制表示加上个负号,方便查看。
如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。
把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。
方法一:逐位判断
根据 与运算 定义,设二进制数字 n ,则有:
若 n & 1 = 0,则 n 二进制 最右一位 为 00 ;
若 n & 1 = 1 ,则 n 二进制 最右一位 为 11 。
根据以上特点,考虑以下 循环判断 :
判断 n 最右一位是否为 11 ,根据结果计数。
将 n 右移一位(本题要求把数字 n 看作无符号数,因此使用 无符号右移 操作)。
算法流程:
初始化数量统计变量 res = 0
循环逐位判断: 当 n = 0时跳出。
res += n & 1 : 若 n & 1 = 1,则统计数 res 加一。
n >>= 1 : 将二进制数字 n无符号右移一位( Java 中无符号右移为 “>>>>>>” ) 。
返回统计数量 res。
class Solution:
def hammingWeight(self, n: int) -> int:
res = 0
while n:
res += n & 1
n >>= 1
return res
方法二:巧用 n & (n - 1)
(n - 1) 解析: 二进制数字 n最右边的 1 变成 0 ,此 1 右边的 0 都变成 1 。
n&(n−1) 解析: 二进制数字 n最右边的 1 变成 0,其余不变。
算法流程:
初始化数量统计变量 res 。
循环消去最右边的 1 :当 n = 0时跳出。
res += 1 : 统计变量加 1 ;
n &= n - 1 : 消去数字 n最右边的 1 。
返回统计数量 res。
class Solution:
def hammingWeight(self, n: int) -> int:
res = 0
while n:
res += 1
n &= n - 1 #每执行一次就会将n最右边的一个1消去一个。统计循环的次数就是1的个数。
return res
备注:
1.语法:str.count(“char”, start,end) 或 str.count(“char”) -> int 返回整数
str —— 为要统计的字符(可以是单字符,也可以是多字符)。
star —— 为索引字符串的起始位置,默认参数为0。
end —— 为索引字符串的结束位置,默认参数为字符串长度即len(str)。
为要统计的字符(可以是单字符,也可以是多字符)。
star —— 为索引字符串的起始位置,默认参数为0。
end —— 为索引字符串的结束位置,默认参数为字符串长度即len(str)。
2.对于二进制的编码的有符号数和无符号数需要了解一下。