本文共 2595 字,大约阅读时间需要 8 分钟。
问题:
对于一个字节(8bit)的变量,求其二进制中1的个数,要求算法的执行效率尽可能的高。
例如把9表示成二进制是1001,有2位是1,因此如果输入9,1的个数为2。
解法一:
可以举一个8位二进制的例子。对于二进制操纵,我们除以一个2,原来数字就会减少一个0(向右移一位)。如果除的过程中有余,那么久表示当前位置有一个1。
以10100010为例:
第一次除以2时,商为1010001,余为0
第二次除以2时,商为101000,余为1
因此,考虑利用整形数据除法的特点,通过相除和判断余数的值进行分析。
int Count(int a){ int count = 0; while(a) { if(a % 2 == 1) { count++; } a = a / 2; } return count;}解法二:位操作
使用位操作同样达到相除的目的。
使用与操作(&)来判断最后一位是不是1,判断完后向右移一位,继续判断。
可以把这个八位数与00000001进行与操作,如果结果为1则表示这个八位数最后一位为1,否则为0。
int Count(int a){ int count = 0; while(a) { count += a & 0x01; a >>= 1; } return count;}位操作要比除法取余操作效率要高许多。
解法三:
作者用到一个巧妙的方法,自己与自己减1相与,(例:10100010 & 10100001 = 10100000)从而到达消去最后一位1,通过统计循环次数达到计算1的个数的目的,这个方法减少了一定的循环次数。
具体解析看看原著。
int Count(int a){ int count = 0; while(a) { a = a & (a-1); count++; } return count;}
解法四:分支操作
解法三的复杂度降到O(M). 其中M为1的个数。这效率已经足够高了。
如果还不满足,还有一种方法。既然才是一个8位的数据(0~255),可以直接0~255的情况罗列出来,使用分支操作,得到答案。
这个方法看似很直接,但是效率可能会比其他方法要低。具体情况具体分析。如果a = 0比较一次就会得到答案,但是a = 255比较255次才得到答案
int Count(int a){ int count = 0; switch(a) { case 0x0: count = 0; break; case 0x1: case 0x2: case 0x4: case 0x8: case 0x10: case 0x20: case 0x40: case 0x80: count = 1; break; case 0x3: case 0x6: case 0xc: case 0x18: case 0x30: case 0x60: case 0xc0: count = 2; break; //..... } return count;}解法五:查表法
直接把0~255相应1的个数直接存在数组中,采取以空间换取时间。
int CountTable[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 };int Count(int a){ return CountTable[a];}
转载地址:http://jwcsi.baihongyu.com/