手撕代码:统计1到n二进制数中1出现的总次数
题目描述:
互娱手撕代码题。
统计从1到n这n个数的二进制表示中1出现的次数。
思路分析:
思路一:直接的做法是从1遍历到n,对于每个数和1做与操作,之后,对于这个数不断做右移操作,不断和1做与操作,直到当前数为0。这样的算法复杂度为O(nlogn)。
思路二:优化时间复杂度,那么考虑用空间换时间。利用n&(n-1)这个操作可以去掉末尾的1。利用递推f(n) = 1+f(n&(n-1))。这样就是利用空间来换时间,时间复杂度为O(n)。
代码:
思路一:
1 int numZeros(int n) 2 { 3 int res=0; 4 for(int i=1; i<=n; i++) 5 { 6 while(i>0) 7 { 8 if(i&1==1) 9 res++; 10 i = i>>1; 11 } 12 } 13 return res; 14 }
思路二:
1 int numZeros(int n) 2 { 3 vector<int>f(n+1, 0); 4 int res=0; 5 for(int i=1; i<=n; i++) 6 { 7 f[i] = 1+f[i&(i-1)]; 8 res += f[i]; 9 } 10 return res; 11 }