【算法練習】還是求二進制數中1的個數

【來源】編程之美


【問題描述】前面的文章介紹瞭如何用較低的時間複雜度,求解一個二進制數中1 的個數。但是時間複雜度仍然是log2(n),其中n表示整數形式,log2(n)表示該整數用二進制表示需要的位數。即,不管二進制位是0還是1都要進行判斷,若二進制數特別大,這樣效率仍然不高。如何進一步提高效率。


【解題】我們只關注的是二進制數中1的個數,那麼我們就數一數1的個數0不用管。可是我們怎麼知道1的個數。設整數v,那麼我們採用位操作,v&(v-1),可以將最低位的1變爲0,消去最低位的1,這樣我們逐個的消除二進制數中1,所有的操作僅與1的個數有關,與0的個數無關。時間複雜度進一步降低。

程序描述如下:

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


【進一步】以上操作已經是時間複雜度降到很低了,那還有沒有更低的呢?

想一想,若僅是讓你求解一個8位二進制數1的個數,以上操作有點“大動干戈”了,8位二進制數,只有256種可能整數,我們完全可以用枚舉的方式列舉出來。

若給出的數是0 ,那麼沒有1,若是1、2、4、8、16、32、64、128則只有1個1……也就那麼9種可能:0個1,1個1,2個1,...,8個1,完全用if-else或者switch-case結構完成。代碼就不列舉了。表面上看起來應該比上面的算法要快,但是想一想,這麼多判斷語句也是消耗時間的,所以平均效率也不如前面的。

【空間換時間】有個聰明人想到了另外一種方法---hash映射。我們將整數與其二進制形式中1的個數做映射,知道了整數值直接可以得出1的個數,hash真的很強大。

這是不是很複雜的結構,我們僅需要用一個數組就能搞定。代碼省略。


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