LeetCode:338. Counting Bits

LeetCode:338. Counting Bits

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]

给定一个数字num,求在0 ≤ i ≤ num范围内的所有数字i的二进制表示中1的个数。

思路一:动态规划
  • 如果一个数字是2的k次幂,那它的二进制表示中肯定只有1个1
  • 如果一个数字不是2的k次幂,那它肯定可以表示为较小的一个2的k次幂和另外一个数之和。

用公式表示就是:
C ( i ) = { 1 i 是 2 的 k 次 幂 C ( m ) + C ( n ) i 不 是 2 的 k 次 幂 C(i)= \begin{cases} 1 & i是2的k次幂\\ C(m)+C(n) & i不是2的k次幂 \end{cases} C(i)={1C(m)+C(n)i2ki2k

Python 代码

class Solution: 
    def isPower(self,n):
        if n < 1:
            return 0
        i = 1
        while i <= n:
            if i == n:
                # 如果等于n,表示是2的k次幂,返回原始值
                return n
            # 如果大于n,表示不是2的k次幂,返回原始值的后面一个2的k次幂
            i <<= 1
        return i

    def countBits(self, num: int) -> List[int]:
        res = []
        
        for i in range(num+1):        
            if (i == 0):
                res.append(0)
            elif (i == 1):
                res.append(1)
            elif (self.isPower(i) != i):
                lastPower = self.isPower(i)>>1
                lastPowerCount = res[lastPower]
                remain = i - lastPower
                remainCount = res[remain]
                res.append(lastPowerCount+remainCount)
            else:
                res.append(1)
                
        return res

然后因为求2的k次幂时间复杂度较高,进一步考虑是否优化。比如对于6(110),它的二进制中的1的个数其实是和3(11)一样的,因为6是3左移以为,右边末尾补零得到的。所以很显然会得到: C ( i ) = C ( i &gt; &gt; 1 ) + i % 2 C(i) = C(i&gt;&gt;1) + i\%2 C(i)=C(i>>1)+i%2,也就是一个数 i 的二进制中的1的个数等于它除以2得到的数二进制中1的个数和除以2余数二进制中1的个数相加。

Python 代码实现

class Solution: 

    def countBits(self, num: int) -> List[int]:
        res = [0]
        for i in range(1,num+1):
            res.append(res[i>>1]+i%2)
        return res
思路二:Python 内置函数 bin

使用内置函数 bin 将一个数转化为二进制,再统计1的个数。

Python 代码实现

class Solution:
    def countBits(self, num: int) -> List[int]:
        target = []
        for i in range(num+1):
            count = bin(i).count('1')
            target.append(count)           
        return target

THE END.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值