一、题目
二、分析
给出时间复杂度为O(n*sizeof(integer))的解答非常容易。但你可以在线性时间O(n)内用一趟扫描做到吗?
题目中给出了这样的要求,所以肯定不能一个数一个数的去求其二进制中1的个数,然后我们可以发现,对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目
,这些数都是连续的。可以知道这是一道动态规划的题。
我们只需要找到当前数值与其前面的哪个数值有关联。
自然数分为奇数和偶数两种,对于一个偶数来说,其二进制中最低位一定是0,比如
A = 10111010;
那其中1的个数与前边哪个数相关呢?因为A的最低位为0,将A后移,不影响其中1的个数。
One(A) = One(A >> 1);
即 One(A) = One(A / 2);
对于奇数来说,其最低位一定为1,
B = 1101011
那么这个数又与前边哪个数相关呢?不难发现,B-1为偶数,而 B 比 (B-1) 多一个1.
B-1 = 1101010
所以 One(B) = One(B-1) + 1;
三、代码
vector<int > ans;
ans.resize(num+1);
ans[0] = 0;
for(int i = 1; i <= num; i ++){
ans[i] = (i%2 == 1)? ans[i-1]+1: ans[i/2];
}
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:7.6 MB, 在所有 C++ 提交中击败了88.53%的用户