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

题目:输入一个整数,输出该数二进制表示中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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章