关于二进制中1的问题解法汇总
问题:
对于一个字节(8位)的无符号整型变量,求二进制中1的个数。
分析:
法一:
(n%2)==1则二进制数n的最低位为1,用count记录下,接下来n减半;
n/=2; (比如 11101001变为 01110100)
所以最基础版的代码如下:
int GetAnswer1(unsigned char data) { int count = 0; while (data) { if ((data % 2) == 1) { count++; } data /= 2; } return count; }
法二:
位操作:
int GetAnswer2(unsigned char data) { int count = 0; while (data) { count+=(data& 0x01); data >>= 1; } return count; }
法三:
比如0101 1101,目标是1,所以只判断1.
代码:
int GetAnswer3(unsigned char data) { int count = 0; while (data) { data&=(data-1); } return count; }
对于法三,详细分析一下:
核心代码是data&=(data-1);
举个例子:
data=1101 1101
data-1=
1101 1101
- 0000 0001
=1101 1100
& 1101 1101
= 1101 1100
第一次结果:从最右边开始数起,刚好最低为就为1,所以清零,该位之前的位不变(即红色部分)。
继续:
data-1=
1101 1100
- 0000 0001
=1101 1011
&1101 1100
=1101 1000
从右往左,遇到0的都变为1,直到遇到1为止,然后清零.
同样1前面的位不变。
接下来同样的操作。。。
所以有几个1就执行几次data&=(data-1)。
法四:
以空间换时间,用一个256大小的数组保存所有的答案,那么查到的的时候就直接O(1)的时间即可。
扩展题目:
第一题:给定两个正整数(二进制表示)A和B,问:把A变为B需要改变多少位?
第一步: unsigned int x=A^B;(异或操作,位相同为0,不同为1)。
第二步: 判断x中1的个数。
第二题:
用一条语句判断一个整数是不是2的整数次方。
分析:
他的二进制位只有一个1,那么就是2的整数次方。
所以:data &= (data-1);
从右往左遇到第一个1清零。
最后判断data是否为0.