您的位置:首页 > 职场人生

剑指Offer_面试题10_二进制中1的个数

2017-07-14 13:32 381 查看
题目:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

这一题与 牛客网_华为机试_015_求int型正整数在内存中存储时1的个数 (十进制转二进制)基本一致,解法请参考。

主要注意的点在于千万不要用模2取余法来统计2的个数,不然面试会死的很惨。首先除法的效率比移位运算要低得多,在实际编程中应尽可能地用移位运算符代替乘除法。下面主要写一下剑指Offer的拓展题

相关题目:

1.用一条语句判断一个整数是不是2的整数次方。

首先这个数必定是正整数,因为是2的整数次方,负数返回false。再者,一个数是2的整数次方,那么他一定只有一位是1,其余全为0,类似于十进制中10的整数次方:10 100 1000 10000 100000,在二进制中是2的整数次方就应该是这种形式。

那么利用原题最优解法中 (n-1) & n 可以把最右边的1去掉的特性,做一次 (n-1)&n,如果为0则证明只有一个1,则证明是2的整数次方。

即 if( ((n-1)&n) == 0) 各位乡亲父老请注意,&优先级低于== ,可是千万要加括号啊,&略高于逻辑计算,算是一个级别吧就这么记忆

2.输入m和n两个整数,计算需要改变m的二进制表示中的多少位,才能得到n。如1010到1101需要改变三位。

首先不要方,本质上是判断两个二进制有多少位不同,想一想位运算中那个运算与相同、不同有关,仔细一想是异或,异或相同为0,不同为1。我们把m和n异或以后,只需要统计1的个数即为不同的位数,也就是需要改变的位数,问题又回到了统计二进制1的问题。

代码:

#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;

//基本解法,eg分别用0001、0010、0100、1000位与,非零则说明有1
int NumOf1(int num)
{
int flag = 1;
int count = 0;
while (flag)
{
if (num & flag)
++count;
flag = flag << 1;
}
return count;
}

//优秀解法 num = (num - 1) & n 将右边的1全置为0
int NumOf1Ex(int num)
{
int count = 0;
while (num)
{
num = (num - 1) & num;
++count;
}
return count;
}

//手动%2法
int NumOf1Manual(int num)
{
int count = 0;
while (num != 0)
{
if (num % 2 != 0)
++count;
num /= 2;
}
return count;
}

//是不是2的整数次方
bool is2pow(int n)
{
if (n <= 0) return false;
//&优先级低于==,要加括号
return ( ((n - 1) & n) == 0);
//return res;
}

//我们之间的二进制差多少位
int changeNum(int m, int n)
{
return NumOf1Ex(m ^ n);
}

int main()
{
int m = 10;
int n = 13;
cout << (8 & 7) << endl;
cout << is2pow(10) << endl;
cout << is2pow(8) << endl;
cout << changeNum(m, n) << endl;
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息