Top 100 Linked Question 修炼------第338题

该博客探讨了LeetCode 338题,要求计算从0到给定非负整数num所有数字在二进制表示中1的个数。博主分享了一种线性时间复杂度、空间复杂度为O(n)的解决方案,通过位操作发现规律:偶数的二进制1的个数等于它除以2的商的二进制1的个数,奇数则加1。并提供了Python实现代码。
摘要由CSDN通过智能技术生成

338. Counting Bits

题目链接

题目解释:给出一个非负整数num.对于每个数字i而言,计算从0~num中每个数字在二进制中包含1的个数。最后的结果通过数组返回。

Example 1:

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

Example 2:

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

Follow up:

  • 很自然的想到时间复杂度为O(n*sizeof(integer))的方案。但是你能在一次遍历,线性时间内完成么?
  • 空间复杂度应该为O(n)
  • 你能像老板一样做么?不能使用类似于c++中的内置函数 __builtin_popcount,或者其他语言的内置函数。

题目分析:首先拿到这个题的时候,我们最直观的想法就是采用取余的方式来进行操作,然后对每个num都进行一次调用即可。但是最后题目有了个follow up.这个方案就pass掉了。但是,也给出这个方案的解题方式,毕竟能接出问题就是王道:
 

class Solution:
    def countBits(self, num):
        """
        :param num:
        :return:
        """
        ans=[]
        for i in range(0,num+1):
            ans.append(self.change2bit(i))
        return ans

    def change2bit(self,num):
        res=[]
        while True:
            tmp=num%2
            res.insert(0,tmp)
            num=num//2
            if num==0:
                break
        return collections.Counter(res)[1]

平常见得最多的方式就是上面这种解题方式,这种方式对于单个求值问题来说是很方便的。

既然这种方法不行,而这题又是考察某个数转换为二进制后1的个数,那么可不可以直接采用 bit operation来完成这样的操作呢?

很显然,本题的直接思想就是需要我们采用Bit operation来完成操作。想想一下,我们那8421来举例子,

对于某个具体的数,若它是偶数,如6,那么其二进制位0110,是不是和3的二进制1一样多。3的二进制位为:0011.这个规律可以一直持续下去。若它是奇数,如7,其二进制为0111,对应的,7/2=3,所以7的二进制中1的个数等于3的二进制中1的个数+1.

通过验证发现,这样的规律是普遍存在的,那么我们可以按照这个规律去解答问题:

PS:很显然,这是个好的解题方案。这个结论也是个好结论,记住就ok了。

下面就是很直观的代码过程:

    def countBits(self,num):
        res = [0]
        for i in range(1, num + 1):
            # 如果i是偶数的话1的个数是和i/2一样多的。如果i是奇数的话,1的个数比i/2多1个。
            res.append(res[i >> 1] + (i % 1))
        return res

Reference

https://leetcode.com/problems/counting-bits/discuss/79544/Python-solution

总结

2019/6/27:有的时候,总会感叹,别人的思路怎么这么巧妙,原来是见得多了,思路也就宽广了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值