【LeetCode】338. 计算比特位的数目

问题描述

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:

  • It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
  • Space complexity should be O(n).
  • Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.

给定一个非负整数num,对于0≤i≤num范围内的每个数字i,计算其二进制表示中的1的个数,并将它们作为数组返回。
跟进:

  • 用运行时O(n*sizeof(integer))提出一个解决方案是非常容易的。但你能在线性时间O(n)内完成吗?
  • 空间复杂度应该是O(n)。
  • 你能像老板那样做吗?在c++或其他任何语言中都不需要使用任何内建函数,如_builtin_popcount。
输入: 2
输出: [0,1,1]

输入: 5
输出: [0,1,1,2,1,2]

 

Python 实现

实现一:转化成二进制数后数 ‘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/

发布了46 篇原创文章 · 获赞 29 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章