求二進位制位中1的個數 程式設計之美

2021-08-27 03:40:47 字數 1160 閱讀 5262

問題描述:對於乙個位元組(8bit)的無符號整型變數,求其二進位制表示中「1」的個數,要求演算法執行效率盡可能高。

這個問題看似簡單,想要得出結果並不難,但是如何使效率盡可能高需要好好考慮。提高效率可以從兩方面著手,乙個是演算法的設計,另乙個是考慮不同操作的執行效率(比如效率最低的是除操作,最高的是按位與、或、非等操作),將低效的操作盡可能換成高效操作也會使得整體時間加快。

文中介紹了5種思路,效率上大致是層層遞進的。從o(lgv)到o(m),最有情況下可達到o(1)。

下面的例子我們都以8bit的二進位制為例;

例如:10100010 第一次除以2商1010001餘0,第二次除2商101000餘1.

int count(byre v)

return num;

}

方法二:我們知道,向右做位操作同樣可以達到除的目的,而且位操作比除操作效率要高。該方法就是承襲了方法1的思想,只不過將除操作用位操作代替。

在向右移位的過程中,我們會把最後一位直接丟棄。因此,需要判斷最後一位是否為1,可以通過「與」操作來完成。將其與0x01進行「與」操作,結果為1則表示當前位為1,否則為0.

int count(byre v)

return num;

}

方法3:前兩種方法複雜度都為o(logv),logv為二進位制的位數。那麼能否繼續降低複雜度呢?

該方法比較巧妙,複雜度可以達到只與1的個數相關,即o(m)的複雜度,其中m為二進位制數種1的個數,具體怎麼做呢?

通過觀察二進位制數我們可以發現,相鄰數的最後乙個二進位制位是不同的,因此我們每做一次v&(v-1)的操作,二進位制位中1的數量就會減少1個,只需記住在二進位制數變為0之前做了多少次操作,即為原二進位制數中1的數量。

int count(byre v)

return num;

}

方法4:這種方法就是萬眾期待的時間複雜度o(1)的思路了。其實很簡單,就是犧牲空間換取時間。將答案羅列在乙個陣列中,直接按索引返回值就好了。

int counttable[256] =

;int count(byre v)

還有一種叫分支操作,大體意思就是用乙個switch語句將所有可能的結果羅列出來,但是在此處效率並不高,不在贅述。

程式設計之美 求二進位制中1的個數

1.問題描述 實現乙個函式,輸入乙個無符號整數,輸出該數二進位制中的1的個數。例如把9表示成二進位制是1001,有2位是1,因此如果輸入9,該函式輸出2 2.分析與解法解法1 利用十進位制和二進位制相互轉化的規則,依次除餘操作的結果是否為1 如下 int count1 unsigned int v ...

求二進位制數中1的個數 《程式設計之美》

求二進位制中1的個數。對於乙個位元組 8bit 的變數,求其二進位制表示中 1 的個數,要求演算法的執行效率盡可能的高。先來看看樣章上給出的幾個演算法 解法一 每次除二,看是否為奇數,是的話就累計加一,最後這個結果就是二進位制表示中1的個數。解法二 同樣用到乙個迴圈,只是裡面的操作用位移操作簡化了。...

程式設計之美 求二進位制數中1的個數

題目 對於乙個位元組的無符號整型變數,求其二進位制表示中 1 的個數,要求演算法的執行效率盡可能高。題目很簡單,一般人都可以用最直接的方法求解出來,通過求餘和模除運算。對二進位制操作過程中,除以乙個2,原來的數就會少乙個0,如果除過程中余1,則表示當前位置有乙個1,計數值加1,很簡單。但從執行效率來...