在编程之美中看到“求二进制数中1的个数”这个问题,读来很受启发遂用Java语言实现相关的方法,写此文章以记之。
方法一:用除和求余,代码如下
public int count(byte v){
int num=0;
while(v!=0){
if(v%2==1)
num++;
v/=2;
}
return num;
}
方法二:用“与”操作和移位,代码如下
public int count(byte v){
int num=0;
while(v!=0){
if((v&0x01)==1)
num++;
v>>>=1;
}
return num;
}
方法三:用1来进行判断,代码如下
public int count(byte v){
int num=0;
while(v!=0){
v&=(v-1);
num++;
}
return num;
}
方法四:用查表法来实现,代码如下
int[] countTable={
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
};
public int count(byte v){
return countTable[v];
}
综合上述方法,个人比较倾向于第三中方法,其算法复杂度只于1的个数有关。在频繁需要用到此功能的应用中可以用第四种方法,是典型的以空间换时间的方法,其时间复杂度为O(1).