题目
今天看到一个面试题,挺有趣的,分享一下。
请实现一个函数,输入一个整数,输出该整数的二进制表示中1的个数。
比如输入9,输出2。
解法1:除法
首先我想到的是用除法,也就是把十进制数转换成二进制数,计算1的个数
int count1(int n)
{
int c=0;
while(n>0)
{
if(n%2==1)
c++;
n/=2;
}
return c;
}
这个方法,在输入整数的时候没有任何问题,但是没有考虑到负数的情况,因为循环条件是n>0,所以所有负数都会输出0。
解法2:考虑负数
因为负数的符号位是1,所以负数的1的个数要比它的相反数加1。
int count1(int n)
{
int c=0;
if(n<0)
{
c++;
n=-n;
}
while(n>0)
{
if(n%2==1)
c++;
n/=2;
}
return c;
}
解法3:位移
其实除法要比位移的运算效率慢很多,所以我们可以使用位移来代替。
int count2(int n)
{
int c=0;
unsigned int flag=1;
while(flag)
{
if(n&flag)
c++;
flag=flag<<1;
}
return c;
}
解法4:位移
解法3已经有优化了,但是还可以优化,减小比较次数。解法3比较的次数等于一个int类型的位数,解法4比较的次数恰好等于1的个数。
int count3(int n)
{
int c=0;
while(n)
{
c++;
n=(n-1)&n;
}
return c;
}