劍指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;
}


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