问题:
对于一个字节(8bit)的变量,求其二进制中1的个数,要求算法的执行效率尽可能的高。
例如把9表示成二进制是1001,有2位是1,因此如果输入9,1的个数为2。
解法一:
可以举一个8位二进制的例子。对于二进制操纵,我们除以一个2,原来数字就会减少一个0(向右移一位)。如果除的过程中有余,那么久表示当前位置有一个1。
以10100010为例:
第一次除以2时,商为1010001,余为0
第二次除以2时,商为101000,余为1
因此,考虑利用整形数据除法的特点,通过相除和判断余数的值进行分析。
[cpp]
view plain
copy
- intCount(inta)
- {
- intcount=0;
- while(a)
- {
- if(a%2==1)
- {
- count++;
- }
- a=a/2;
- }
- returncount;
- }
解法二:位操作
使用位操作同样达到相除的目的。
使用与操作(&)来判断最后一位是不是1,判断完后向右移一位,继续判断。
可以把这个八位数与00000001进行与操作,如果结果为1则表示这个八位数最后一位为1,否则为0。
[cpp]
view plain
copy
- intCount(inta)
- {
- intcount=0;
- while(a)
- {
- count+=a&0x01;
- a>>=1;
- }
- returncount;
- }
位操作要比除法取余操作效率要高许多。
解法三:
作者用到一个巧妙的方法,自己与自己减1相与,(例:10100010 & 10100001 = 10100000)从而到达消去最后一位1,通过统计循环次数达到计算1的个数的目的,这个方法减少了一定的循环次数。
具体解析看看原著。
[cpp]
view plain
copy
- intCount(inta)
- {
- intcount=0;
- while(a)
- {
- a=a&(a-1);
- count++;
- }
- returncount;
- }
解法四:分支操作
解法三的复杂度降到O(M). 其中M为1的个数。这效率已经足够高了。
如果还不满足,还有一种方法。既然才是一个8位的数据(0~255),可以直接0~255的情况罗列出来,使用分支操作,得到答案。
这个方法看似很直接,但是效率可能会比其他方法要低。具体情况具体分析。如果a = 0比较一次就会得到答案,但是a = 255比较255次才得到答案
[cpp]
view plain
copy
- intCount(inta)
- {
- intcount=0;
- switch(a)
- {
- case0x0:
- count=0;
- break;
- case0x1:
- case0x2:
- case0x4:
- case0x8:
- case0x10:
- case0x20:
- case0x40:
- case0x80:
- count=1;
- break;
- case0x3:
- case0x6:
- case0xc:
- case0x18:
- case0x30:
- case0x60:
- case0xc0:
- count=2;
- break;
- //…..
- }
- returncount;
- }
解法五:查表法
直接把0~255相应1的个数直接存在数组中,采取以空间换取时间。
[cpp]
view plain
copy
- intCountTable[256]=
- {
- 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
- };
- intCount(inta)
- {
- returnCountTable[a];
- }