338. 比特位计数-leetcode刷题(C++)

一、题目

338. 比特位计数

二、分析

给出时间复杂度为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%的用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值