求二進制數中"1"的個數

本題同樣來自《編程之美》。


對於一個字節(8bit)的無符號整型變量,求其二進制表示中“1”的個數。


笨方法:

對於二進制操作,除以一個2,原來的數字就會減少一個0.(可以類比十進制,十進制除以一個10,則相應會減少一個0)

如果除的過程中有餘,那麼就表示當前位置有一個1.

#include<stdio.h>
typedef unsigned char BYTE;
int Count(BYTE v)
{
	int num = 0;
	while(v)
	{
		if(v%2==1)
			num++;
		v=v/2;
	}
	return num;
}
int main()
{
	BYTE b1 = 0;
	BYTE b2 = 129;
	BYTE b3 = 255;
	printf("b1 :%d\n",Count(b1));
	printf("b2 :%d\n",Count(b2));
	printf("b3 :%d\n",Count(b3));
	return 0;
}


好方法:

右移操作同樣可以達到相除的目的。

右移後,與00000001進行“與”操作。

int Count(BYTE v)
{
	int num = 0;
	while(v)
	{
		num+=v&0x01;
		v>>=1;
	}
	return num;
}



聰明方法:

雖然使用位操作的效率比笨方法高多了,但是,時間複雜度仍爲O((log2)v)。

想辦法使時間複雜度只與“1”的個數相關。

若v爲:01000000,則v-1爲:00111111。兩者相與爲0。

若v爲:01100000,則v-1爲:01011111。兩者相與爲01000000。此時和第一種情況一樣。再次操作後,爲0。

所以,根據這個規律,我們考慮v和v-1相與,統計結果爲0之前的次數即爲“1”的個數。

int Count(BYTE v)
{
	int num = 0;
	while(v)
	{
		v&=(v-1);
		num++;
	}
	return num;
}


此外,還有空間換時間的方法。

將所有的256種情況存儲在數組中。

根據v的不同,直接取相應的情況即可。

算法時間複雜度僅爲O(1)。


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