问题描述:
对于1个字节(8bit)无符号整型变量,求其二进制表示中“1”的个数
解法一:除2取余
(对于二进制操作,除以一个2,原来的数字会减少一个0。如果除的过程中有余数,就表示当前位置有一个1)
解法二:位移操作
(对于二进制向右移位操作同样可以达到解法一的目的,但是比除、余操作效率高)
解法三:
只考虑有1的情况(清除最低位的1)
解法四:分支操作
(看似直接,但是执行效率可能会低于解法二、三)空间换时间
解法五:查表法
空间换时间
把0~255中“1”的个数直接存储在数组中,v作为数组下标,countTable[v]就是v中“1”的个数。算法时间复杂度仅为O(1)
扩展问题:
问题1:对于32位的DWORD,可以动态建表或静态建表
1)动态建表
由于表示在程序运行时动态创建的,所以速度上肯定会慢一些,
把这个版本放在这里,有两个原因
1.填表的方法,这个方法的确很巧妙。
2.类型转换,这里不能使用传统的强制转换,而是先取地址再转换成对应的指针类型。
代码如下:
2)静态建表
首先构造一个包含256个元素的表table,table[i]即i中1的个数,
这里的i是[0-255]之间任意一个值。然后对于任意一个32bit无符号整数n,
我们将其拆分成四个8bit,然后分别求出每个8bit中1的个数,再累加求和即可,这里用移位的方法,每次右移8位,并与0xff相与,取得最低位的8bit,累加后继续移位,如此往复,直到n为0。所以对于任意一个32位整数,需要查表4次。以十进制数2882400018为例,其对应的二进制数为10101011110011011110111100010010,对应的四次查表过程如下:红色表示当前8bit,绿色表示右移后高位补零。
第一次(n & 0xff) 10101011110011011110111100010010
第二次((n >> 8) & 0xff) 00000000101010111100110111101111
第三次((n >> 16) & 0xff)00000000000000001010101111001101
第四次((n >> 24) & 0xff)00000000000000000000000010101011
代码如下:
2.问题2,给定A和B,问把A变为B需要改变多少位?也就是说有多少位不同?
首先异或,则不同的位结果为1,然后统计异或结果中1的个数;