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.
Credits:

Special thanks to @ syedee for adding this problem and creating all test cases.

这道题给我们一个整数n,然我们统计从0到n每个数的二进制写法的1的个数,存入一个一维数组中返回,题目中明确表示不希望我们一个数字一个数字,一位一位的傻算,而是希望我们找出规律,而且题目中也提示了我们注意 [2-3], [4-7], [8-15] 这些区间的规律,那么我们写出0到 15 的数的二进制和1的个数如下:

-------------

-------------

-------------

-------------

我最先看出的规律是这样的,除去前两个数字0个1,从2开始,2和3,是 [21, 22) 区间的,值为1和2。而4到7属于 [22, 23) 区间的,值为 1,2,2,3,前半部分1和2和上一区间相同,2和3是上面的基础上每个数字加1。再看8到 15,属于 [23, 24) 区间的,同样满足上述规律,所以可以写出代码如下:

解法一:

class Solution {
public:
vector<int> countBits(int num) {
if (num == ) return {};
vector<int> res{, };
int k = , i = ;
while (i <= num) {
for (i = pow(, k - ); i < pow(, k); ++i) {
if (i > num) break;
int t = (pow(, k) - pow(, k - )) / ;
if (i < pow(, k - ) + t) res.push_back(res[i - t]);
else res.push_back(res[i - t] + );
}
++k;
}
return res;
}
};

下面来看一种投机取巧的方法,直接利用了 built-in 的函数 bitset 的 count 函数可以直接返回1的个数,题目中说了不提倡用这种方法,写出来只是多一种思路而已:

解法二:

class Solution {
public:
vector<int> countBits(int num) {
vector<int> res;
for (int i = ; i <= num; ++i) {
res.push_back(bitset<>(i).count());
}
return res;
}
};

下面这种方法相比第一种方法就要简洁很多了,这个规律找的更好,规律是,从1开始,遇到偶数时,其1的个数和该偶数除以2得到的数字的1的个数相同,遇到奇数时,其1的个数等于该奇数除以2得到的数字的1的个数再加1,参见代码如下:

解法三:

class Solution {
public:
vector<int> countBits(int num) {
vector<int> res{};
for (int i = ; i <= num; ++i) {
if (i % == ) res.push_back(res[i / ]);
else res.push_back(res[i / ] + );
}
return res;
}
};

下面这种方法就更加巧妙了,巧妙的利用了 i&(i - 1), 这个本来是用来判断一个数是否是2的指数的快捷方法,比如8,二进制位 1000, 那么 8&(8-1) 为0,只要为0就是2的指数, 那么我们现在来看一下0到 15 的数字和其对应的 i&(i - 1) 值:

i    binary ''  i&(i-)

-----------------------

-----------------------

-----------------------

-----------------------

我们可以发现每个i值都是 i&(i-1) 对应的值加1,这样我们就可以写出代码如下:

解法四:

class Solution {
public:
vector<int> countBits(int num) {
vector<int> res(num + , );
for (int i = ; i <= num; ++i) {
res[i] = res[i & (i - )] + ;
}
return res;
}
};

参考资料:

https://leetcode.com/problems/counting-bits/

https://leetcode.com/discuss/92796/four-lines-c-time-o-n-space-o-1

https://leetcode.com/discuss/92694/my-408-ms-c-solution-using-bitset

https://leetcode.com/discuss/92698/my-448ms-c-easy-solution-o-n-time-and-o-n-space

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Counting Bits 计数位的更多相关文章

  1. LeetCode Counting Bits

    原题链接在这里:https://leetcode.com/problems/counting-bits/ 题目: Given a non negative integer number num. Fo ...

  2. LeetCode——Counting Bits

    Question Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calcu ...

  3. Leetcode之动态规划(DP)专题-338. 比特位计数(Counting Bits)

    Leetcode之动态规划(DP)专题-338. 比特位计数(Counting Bits) 给定一个非负整数 num.对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数 ...

  4. 【LeetCode】338. Counting Bits (2 solutions)

    Counting Bits Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num  ...

  5. LN : leetcode 338 Counting Bits

    lc 338 Counting Bits 338 Counting Bits Given a non negative integer number num. For every numbers i ...

  6. 2016.5.16——leetcode:Reverse Bits(超详细讲解)

    leetcode:Reverse Bits 本题目收获 移位(<<  >>), 或(|),与(&)计算的妙用 题目: Reverse bits of a given 3 ...

  7. Week 8 - 338.Counting Bits & 413. Arithmetic Slices

    338.Counting Bits - Medium Given a non negative integer number num. For every numbers i in the range ...

  8. leetcode 上的Counting Bits 总结

    最近准备刷 leetcode  做到了一个关于位运算的题记下方法 int cunt = 0; while(temp) { temp = temp&(temp - 1);  //把二进制最左边那 ...

  9. leetcode 338. Counting Bits,剑指offer二进制中1的个数

    leetcode是求当前所有数的二进制中1的个数,剑指offer上是求某一个数二进制中1的个数 https://www.cnblogs.com/grandyang/p/5294255.html 第三种 ...

随机推荐

  1. SQL Tuning 基础概述02 - Explain plan的使用

    1.explain plan的使用 SQL> explain plan for delete from t_jingyu; Explained. SQL> select * from ta ...

  2. C#开发微信门户及应用(22)-微信小店的开发和使用

    在做企业电子商务方面,微信小店虽然较淘宝天猫等起步较晚,但是作为一个电商平台,这个影响力不容忽视,结合微信的特点和便利,微信小店具有很好的粘合性和广泛的用户基础,因此花费一定的时间,在这方面做深入的研 ...

  3. 解决NTKO Office中文文件名保存到服务器时出现乱码的问题

    再使用NTKO office控件时,在ntko往服务器提交文件时,中文文件名会出现乱码的问题! 其实解决这个问题可以换一种思路,在ntko往服务器提交文件时英文肯定是不会出现乱码的问题的! 那么想办法 ...

  4. java重载与覆写

    很多同学对于overload和override傻傻分不清楚,建议不要死记硬背概念性的知识,要理解着去记忆. 先给出我的定义: overload(重载):在同一类或者有着继承关系的类中,一组名称相同,参 ...

  5. Delphi_07_Delphi_Object_Pascal_基本语法_05_函数参数

    这里主要讨论Delphi中函数.方法的相关内容. 一.工程文件 { Delphi语法方法和函数 1.方法 2.函数 } program Routine; {$APPTYPE CONSOLE} uses ...

  6. jdk链表笔记

    LinkedList LinkedList是双链表,并且有头尾指针 数据结构 public class LinkedList extends AbstractSequentialList implem ...

  7. 5.1 JS中Object类型

    1.Object类型是引用类型中的一种. 2.创建Object实例(对象)的方式: 方式1:使用new操作符,后面跟上Object构造函数.如: var obj = new Object();//创建 ...

  8. MapFile生成WMS

    MAP  NAME "HBWMS"  STATUS ON  SIZE 800 600  EXTENT 107.795 28.559 116.977 33.627  UNITS ME ...

  9. React Native windows搭建记录

    因为是window电脑上运行的,所以测试的是安卓 1: 安装jdk:jdk-8u45-windows-x64.exe 2: 配置JAVA的环境变量 在安卓的配置基础上添加一个变量ANDROID_HOM ...

  10. android Fragments介绍

    Fragments是Android3.0引入的概念,译为片段.碎片,为了解决不同屏幕分辩率的动态和灵活UI设计. Fragment表现Activity中UI的一个行为或者一部分.可以将多个fragme ...