zoukankan      html  css  js  c++  java
  • 【Leetcode】338. Bit位计数

    每次刷leetcode都有一种发现新大陆的感觉。

    题目链接:https://leetcode-cn.com/problems/counting-bits/description/

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

    示例:
    比如给定 num = 5 ,应该返回 [0,1,1,2,1,2].

    进阶:

      • 给出时间复杂度为O(n * sizeof(integer)) 的解答非常容易。 但是你可以在线性时间O(n)内用一次遍历做到吗?
      • 要求算法的空间复杂度为O(n)。
      • 你能进一步完善解法吗? 在c ++或任何其他语言中不使用任何内置函数(如c++里的 __builtin_popcount)来执行此操作。
    
    
    0    0000    0
    -------------
    1    0001    1
    -------------
    2    0010    1
    3    0011    2
    -------------
    4    0100    1
    5    0101    2
    6    0110    2
    7    0111    3
    -------------
    8    1000    1
    9    1001    2
    10   1010    2
    11   1011    3
    12   1100    2
    13   1101    3
    14   1110    3
    15   1111    4

    找规律,以分割线为界限。比如4-7。4,5和2,3相同,但是6,7却是2,3 加 1. 而8-15也符合类似的规则。可以用这个规律写下代码。

    大神解法:

    1 public int[] countBits(int num) {
    2     int[] f = new int[num + 1];
    3     for (int i=1; i<=num; i++) 
    4         f[i] = f[i >> 1] + (i & 1);
    5     return f;
    6 }

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

    i    bin       '1'    i&(i-1)
    0    0000    0
    -----------------------
    1    0001    1    0000
    -----------------------
    2    0010    1    0000
    3    0011    2    0010
    -----------------------
    4    0100    1    0000
    5    0101    2    0100
    6    0110    2    0100
    7    0111    3    0110
    -----------------------
    8    1000    1    0000
    9    1001    2    1000
    10   1010    2    1000
    11   1011    3    1010
    12   1100    2    1000
    13   1101    3    1100
    14   1110    3    1100
    15   1111    4    1110

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

     1 class Solution {
     2 public:
     3     vector<int> countBits(int num) {
     4         vector<int> res(num + 1, 0);
     5         for (int i = 1; i <= num; ++i) {
     6             res[i] = res[i & (i - 1)] + 1;
     7         }
     8         return res;
     9     }
    10 };

    唉,都是人才啊。怎么想到的

  • 相关阅读:
    变量可变性问题
    Android 创建Listener监听器形式选择:匿名内部类?外部类?
    linux下安装zookeeper
    翻页工具类
    将哈夫曼树转化成二叉树
    Activity的启动流程分析
    题目1186:打印日期
    数据库设计--数据流图(DFD)
    c#基础之数组
    10.3.1 一个CONNECT BY的样例
  • 原文地址:https://www.cnblogs.com/wenbochang/p/9032822.html
Copyright © 2011-2022 走看看