Skip to content

Latest commit

 

History

History
132 lines (90 loc) · 3.76 KB

0338._Counting_Bits.md

File metadata and controls

132 lines (90 loc) · 3.76 KB

338. Counting Bits

难度: Medium

刷题内容

原题连接

内容描述

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.

Example 1:

Input: 2
Output: [0,1,1]
Example 2:

Input: 5
Output: [0,1,1,2,1,2]
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.

解题方案

思路 1 - 时间复杂度: O(Nk) k is number of bits in num*- 空间复杂度: O(N)******

O(n*sizeof(integer)) 算法,其实就是把count of 1 bit拿来用:

class Solution(object):
    def countBits(self, num):
        """
        :type num: int
        :rtype: List[int]
        """
        def hammingWeight(n):
        	cnt = 0
        	while n != 0:
        		n &= n -1
        		cnt += 1
        	return cnt

        res = []
        for i in range(num+1):
        	res.append(hammingWeight(i))
        return res

Follow up:

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.

思路 1 - 时间复杂度: O(N)- 空间复杂度: O(N)******

DP 算法

DP 的思路其实不难,就是“把每天当成是末日来相待”,并且这一天发生的事能记下来就记下来。 转换到实际问题上,就是把每一步都当时是最后一步来操作,然后沿途记下一些以后需要的数据即可。

本题是求二进制数中1的个数,首先,创建一个数组dp,数组的索引i就是数字i,索引i对应的值就是数字i二进制数的1的个数。

我们知道,任何一个十进制数字num都可以转换成二进制,并且,转换后的二进制长度是x = floor(log(num, 2)) + 1位,这x位数字除了第一位是1之外,其他位都是01

所以,可以把num拆成两个数的和,其中第一个数是p = 2**(x-1),第二个数就是num - p。如果num == p, 因为p = 2**(x-1)中数字1的个数是1,那么此时num的二进制数中的1的个数就是1,即dp[num] = 1,否则,dp[num] = dp[p] + dp[num-p](num-p一定小于p)。

总结一下,关键点在于c = a + b,如何找到合适的ab.

首先只有一轮循环,在每一轮循环里面有log函数,但是基本上可以忽略不计,所以总时间复杂度为O(N),空间也为O(N)

class Solution(object):
    def countBits(self, num):
        """
        :type num: int
        :rtype: List[int]
        """
        from math import floor, log
        dp = [0] * (num+1)
        for i in range(1, num+1):
            x = floor(log(i, 2)) + 1
            p = int(pow(2, x-1))
            if p == i:
                dp[i] = 1
            else:
                dp[i] = dp[p] + dp[i-p]
        return dp

思路 2 - 时间复杂度: O(N)- 空间复杂度: O(N)******

dp的另外一种方法,状态方程为 P(x) = P(x&(x-1)) + 1

beats 95.17%

class Solution(object):
    def countBits(self, num):
        """
        :type num: int
        :rtype: List[int]
        """
        dp = [0] * (num+1)
        for i in range(1, num+1):
            dp[i] = dp[i&(i-1)] + 1
        return dp