解法一:
对于二进制数的操作,我们知道除以一个2,原来的位数将会减少一位,如果除的过程中有余数,那么就表示当前位置有一个1,否则为0。
以10100010为例:
第一次除以2时,商为1010001,余0。
第二次除以2时,商为101000,余1。
第三次除以2时,商为10100,余0。
第四次除以2时,商为1010,余0。
第五次除以2时,商为101,余0。
第六次除以2时,商为10,余1。
第七次除以2时,商为1,余0。
第八次除以2时,商为0,余1。
解法二:
采用位操作。
以10100001为例:
右移一位,结果为1010000,移出位为1
再右移一位,结果为101000,移出位为0
再右移一位,结果为10100,移出位为0
………
比上面更好的解决了问题,还有更简单的做法吗?
解法三:
位操作虽然比除,求余操作的效率高了很多。但是,时间复杂度没有改变,时间复杂度还是O(log2v),log2v为二进制的位数。现在我们想设计出一种算法解决这个问题时,只与二进制表达式中的1的个数有关的(先介绍按位与)
以10100001为例:
10100001 10100000 10000000
&10100000 &10011111 &01111111
10100000 10000000 00000000
解法四:
也许你感到上面的算法已经足够快了,但是这是最好的解法吗?难道不能设计出O(1)的解法,即当你输入一个数时,对应的结果也知道了。
扩展问题:给你两个整数A和B,问把A变成B需要改变多少位。
解放三代码:
#include
using namespace std;
int main()
{
int N,n=0;
while(cin>>N)
{
while(N)
{
N=N&(N-1);
n++;
}
cout<}
}