问题描述:对于一个字节(8bit)的无符号整形变量,求其二进制表示中“1”的个数,要求算法的执行效率尽可能提高。
解法一:
可以举一个八位的二进制例子来进行分析。对于二进制操作,我们知道,除以一个2.原来的数字会减少一个0.如果除的过程中有余,那么就表示当前位置有一个1.
以10100010为例:第一次除以2时,商为1010001,余为0.第二次除以2时,商为10100,余为1.
代码清单:
int count(BYTE v)
{
int num=0;
while(v)
{
if(v%2==1)
num++;
}
v=v/2;
}
return num:
}
解法二:使用位操作
向右移位除同样可以达到相除的目的。
在向右移位的过程中,我们会把最后一位直接丢弃。因为需要判断最后一位是否为1,而与操作可以达到目的。
代码如下
int count(BYTE V)
{
int num=0;
while(v)
{
num+=v&0x01;
v>>1;
}
return num;
}
复杂度o(log2v)
解法三
进一步降低复杂度,让算法的复杂度只与“1”的个数有关。
代码如下:
int count(BYTE v)
{
int num=-0;
while(v)
{
v&=(v-1);
num++;
}
return num;
}
解法四:
以空间换取时间:
将所有256种情况都列出来:
int contTable[256] =
{
0,1,1,2,1,2,2,3,1,...................................}后面的都省略了。
int count(BYTE v)
{
return coutTable[v];
}
附加题:
另一个相关的问题,给定两个正整数(二进制数表示)A和B,问把A变成B需要改变多少位(bit)?也就是说,整数A和B的二进制表示中有多少位是不同的。
思路:
把两个整数 A, B 异或, 然后又回归到判断 1 的个数
int Count( int a, int b)
{
int num = 0;
int v = a ^ b;
while(v)
{
v &= (v-1);
num++;
}
return num;
};