在面试中被问到这一题:判断32位无符号整数二进制中1的个数,虽然不难,但要求层层优化。现在整理一下:
1、基本思路:
#include <iostream>
using namespace std;
int findone(unsigned int n){
for(int i=0;n>0;n>>=1)
i+=(n&1);
return i;
}
int main(){
int n;
cin>>n;
cout<<findone(n)<<endl;
return 0;
}
using namespace std;
int findone(unsigned int n){
for(int i=0;n>0;n>>=1)
i+=(n&1);
return i;
}
int main(){
int n;
cin>>n;
cout<<findone(n)<<endl;
return 0;
}
这样的时间复杂度是T(m)=m,取决于二进制数的位数m。如果要求在更短时间内求出,应该如何做呢?如果findone函数被反复调用(成千上万次调用),那应该怎么优化呢?
其实就是空间换时间的思想:可以预建立一个表,存放了从0~2^32每个数中1的个数,用时去查一下表就知道了。但这样显然要耗费很多的空间(至少2^32/(256/32)=512MB,哈哈,正是一般内存大小)。于是需要再优化:存放0-255每个数中1的个数,然后分段查询。如下面把32位数分为4段,每段一个字节,所以有一个256大小供查询的表:
char tOne[256]="\0\1\1\2\1\2……"; //后面省略
int findone(unsigned int n){
for(int i=0;n>0;n>>=8)
i+=tOne[n&255];
return i;
}
int findone(unsigned int n){
for(int i=0;n>0;n>>=8)
i+=tOne[n&255];
return i;
}
4、又看到有道MS的笔试题殊途同归:
int func(unsigned int n){
int count=0;
while(n>0){
n&=(n-1);
count++;
}
return count;
}
int count=0;
while(n>0){
n&=(n-1);
count++;
}
return count;
}