Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array.
Follow up:
给定一个非负整数num,对于0≤i≤num范围内的每个数字i,计算其二进制表示中的1的个数,并将它们作为数组返回。
跟进:
输入: 2
输出: [0,1,1]
输入: 5
输出: [0,1,1,2,1,2]
实现一:转化成二进制数后数 ‘1’ 的个数。不用说,这是一个很耗内存的实现方法,每次转换成二进制数时都需要使用新的内存。
class Solution(object):
def countBits(self, num):
"""
:type num: int
:rtype: List[int]
"""
bitCnt = [0]
for n in range(1,num+1):
bitCnt.append(format(n,'b').count('1'))
return bitCnt
实现二:寻找规律。二进制数与 2 的 n 次方有很密切的关系,那么我们可以观察一下当入参 num 为 2 的 n 次方时,所得的结果有什么规律:
[0]
[0, 1]
[0, 1, 1, 2]
[0, 1, 1, 2, 1, 2, 2, 3]
[0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4]
...
没看出来?给个提示:看看每一个数组中,新增的后半部分元素与前半部分有什么关系。
没错,后半部分的每一个元素相当于前半部分每个元素加一后的结果。
但是这个方法存在一个缺点就是,当入参 num 较大时,一个极端情况 num = 2^n + 1,这样我们就需要计算到 2^(n+1),但后面的 2^n - 1 个数都会被抛弃,因此存在着运算资源的浪费。
class Solution(object):
def countBits(self, num):
"""
:type num: int
:rtype: List[int]
"""
bitCnt = [0]
while len(bitCnt) < num+1:
bitCnt.extend([i+1 for i in bitCnt])
return bitCnt[:num+1]
实现三:动态规划。
分析相邻两个整数在二进制表示下的关系。如果 n 是奇数,那么其最低比特位为1,则 n>>1 (表示 n 右移一位)出现 1 的个数再加 1 就是 n 出现 1 的个数(奇数右移一位会丢失最低位的 1);如果 n 是偶数,则右移一位后,出现 1 的个数不变。其中,我们所要知道的 n>>1 出现 1 的个数,必然在前面计算已经得到,所以这一题可以使用动态规划来解决。
class Solution(object):
def countBits(self, num):
"""
:type num: int
:rtype: List[int]
"""
bitCnt = [0]*(num+1)
for i in range(1, num+1):
bitCnt[i] = bitCnt[i>>1] + i%2
return bitCnt
链接:https://leetcode.com/problems/counting-bits/