专栏名称: 每日一道算法题
学习算法是一种信仰,每天都需要坚持!
目录
相关文章推荐
51好读  ›  专栏  ›  每日一道算法题

[每日一题]DP总结之 338. Counting Bits

每日一道算法题  · 公众号  · 算法  · 2017-04-26 22:58

正文

问题描述

题目难度: 中等

做题日期: 2017 年 4 月 26 号


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:
For
num = 5 you should return [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.

思路分析


没有阅读前两天总结的读者可以先看看前两篇基础介绍:

[每日一题]DP小结一:重叠子问题

[每日一题]DP二:最优子结构


DP思路

这几天一直在总结 DP 的特点,希望能找到一般性的解题思路。笔者认为,DP 题的难点在于构建最优子结构。只要构造了最优子结构,一般就比较容易解题了。 构造最优子结构的方法有两种:倒推发现 n 与 0 到 n - 1 的关系;使用 DFS 和 递归 方法,从 0 到 n 发现规律。


今天这道题的解法试图通过观察其特点发现规律。这也是一般性的思考问题的方法: 通过画图,将抽象的问题具体化 ,通过具体的例子来发现规律,最后推广到 n 的规模。


假设 n = 10 , 那么 0 到 10 对应的 二进制数 和 1 的个数 如下图所示

根据是否能被 2 整除,我们可以将 n 分成 偶数 和 奇数 。


n 为偶数

当 n 为偶数的时候, 比如 10 , 我们可以发现其 1 的个数 与 5 的 1 的个数相等。如下图所示

实际上,通过对比 10 二进制数 1010 跟 5 的二进制数 101,我们可以发现: 5 向左移动一位后就等于 10 。所以 10 的 1 的个数 与 5 的 1 的个数相等(在左移的过程中,没有增加 1 ,只在最后面补了一个 0)。


n 为奇数

如下图所示,当 n = 9 的是,我们可以发现 9 的 1 的个数等于 4 的 1 的个数 在 加 1 。

实际上,通过对比 9 的二进制数 1001 与 4 的二进制数 100, 我们可以发现:

100(4) 左移动一位以后变成了 1000, 然后加 1 ,正好等于 1001 (9) 。所以 9 的 二进制值 的 1 个数等于 4(实际上是 9 除以 2 的值)的二进制值的 1 的个数在加 1。







请到「今天看啥」查看全文