动态规划题,但是很有技巧性,针对于位运算和二进制有点说法。
338. 比特位计数
给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。
class Solution {
public:
vector<int> countBits(int n) {
vector<int>ans(n+1);
ans[0]=0;
for(int i=1;i<=n;++i){
ans[i]=ans[i>>1]+(i&1);
}
return ans;
}
};
首先说这是一个统计二进制数的1的个数的题,通过别人对这道题规律的解答来看,就是说:
如果是奇数,结果就是它前一个数1的个数+1
如果是偶数,结果就是它自身一半的数的1的个数
总结就是,都与自身一半看齐。
同时为了区分奇偶性,引入了i&1这种操作。
这个操作乍一看不知道是干啥的,仔细研究发现,如果是奇数i,那二进制结果必然是1,结果也就是1,如果是偶数,结尾是0,结果就会是0。
同时,采用左移右移的操作进行效率上的简化。
得到:ans[i]=ans[i>>1]+(i&1)这种“高端”操作,要我自己想肯定想不出来...
也就是说,如果是奇数,就会+1,不是奇数就不加。
这类题我感觉就要靠经验了,因为你考试时候现想还是有点费劲的。
关于位运算,有操作x&(x-1)
x&(x-1)能消去二进制x的最后一个1,也就是说,反复对一个数进行循环的这种操作,得出的结果,就是该数字二进制,1的个数。