LeetCode(338) 比特位计数

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> LeetCode(338) 比特位计数

本题来自LeetCode:338. 比特位计数,

题目内容

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

示例 1: 输入: 2 输出: [0,1,1]

示例 2: 输入: 5 输出: [0,1,1,2,1,2]

进阶:
  • 给出时间复杂度为`O(n*sizeof(integer))`的解答非常容易。但你可以在线性时间`O(n)`内用一趟扫描做到吗?
  • 要求算法的空间复杂度为`O(n)`。
  • 你能进一步完善解法吗?要求在C++或任何其他语言中不使用任何内置函数(如C++中的 `__builtin_popcount`)来执行此操作。

题目分析

本题明显可以使用暴力法解答出来,对每个数值采用 位移法统计,但是时间复杂度为O(n*sizeof(integer)),不满足进阶的要求。
定义 bits[n]为值 num的比特位1的个数。
初步分析,没有什么头绪。故先手工计算下前面几个数字,期望能够发现些规律:

num二进制bits[num]|------

从上面的表格中,显然可以发现,值为2的 n次方时,比特位1的个数为1,即 bits[2^n] = 1;将上面的分析的结果继续拆分:

num二进制bits[num]表达式|------

现在规律已经非常明显了,可通过动态规划来解答此题。当 num不为2的 n次方时,比特位1的个数为 bits[num] = bits[2^n] + bits[num - 2^n],其中 2^n num 2^(n+1)

添加解答

整理以上分析,完整的解答过程如下:


class Solution {
    public int[] countBits(int num) {
        int[] bits = new int[num + 1];
        if(num == 0) {
            return bits;
        }
        bits[1] = 1;
        int temp = 1;   // 记录2的n次方
        for(int i = 2; i = num; i ++) {
            // 若i是2的次方,直接设置为1
            if(temp  1 == i) {
                temp = 1;
                bits[i] = 1;
            } else {
                bits[i] = bits[temp] + bits[i - temp];
            }
        }
        return bits;
    }
}

原文始发于微信公众号(xiaogan的技术博客):

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> LeetCode(338) 比特位计数


 上一篇
LeetCode(357)计算各个位数不同的数字个数 LeetCode(357)计算各个位数不同的数字个数
本题来自LeetCode:357. 计算各个位数不同的数字个数 题目详情给定一个非负整数 n,计算各位数字都不同的数字 x的个数,其中 0≤x10^n 。 示例: 输入: 2 输出: 91 解释: 答案应为除去 11,22,33,44,5
2021-04-05
下一篇 
深入理解 Java 虚拟机【4】HotSpot 垃圾收集器 深入理解 Java 虚拟机【4】HotSpot 垃圾收集器
作者:杨立滨 链接:https://github.com/yanglbme/jvm 知音专栏 程序员的出路 写程序时该追求什么,什么是次要的? 如何准备Java初级和高级的技术面试 上一篇:深入理解 Java 虚拟机【3】垃圾收