標籤:style class blog code java http
今天在華為OJ上遇到這麼一個題目,很簡單,但是卻總是得不到最好的成績記錄。因此比較了自己的程式、思路與別人的異同,發現還是有很大區別的,遂記錄如下。
題目——
輸入一個int型整數,求該整數的二進位在記憶體中有多少個1。例如輸入10,由於其二進位表示為1010,有兩個1,因此輸出2。
思路1
<span style="font-size:18px;">public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int m = scanner.nextInt(); int num = 0; while(m>0){ m&=(m-1); num++; } } </span><span style="font-size: 16pt;"> </span>
這是最常規的思路。直接利用移位去算,始終判斷最後一位是不是1,然後計數。這也是我一開始所所想到的,但是,這種寫法只得到了60分。
思路2
<span style="font-size:18px;">private static int count_ones(int a) { a = (a & 0x55555555) + ((a >> 1) & 0x55555555); a = (a & 0x33333333) + ((a >> 2) & 0x33333333); a = (a & 0x0f0f0f0f) + ((a >> 4) & 0x0f0f0f0f); a = (a & 0x00ff00ff) + ((a >> 8) & 0x00ff00ff); a = (a & 0x0000ffff) + ((a >> 16) & 0x0000ffff); return a; }</span><span style="font-size: 16pt;"></span>
這是我看別人拿了滿分的答案。這種思路比較難想到。一開始我怎麼都想不明白他是怎麼想出來的。直到翻看書籍,碰巧在《編程之美》上有記載這個題目,並且給出了五種解法。其中有兩種就是以上兩種。
這道題的本質相當於求位元的 Hamming 權重,或者說是該位元與 0 的 Hamming 距離,這兩個概念在資訊理論和編碼理論中是相當有名的。在二進位的情況下,它們也經常被叫做 population count 或者 popcount 問題,比如 gcc 中就提供了一個內建函數:int __builtin_popcount (unsigned int x) 輸出整型數二進位中 1 的個數。但是 GCC 的 __builtin_popcount 的實現主要是基於查表法做的,跟編程之美中解法 5 是一樣的。Wikipedia 上的解法是基於分治法來做的,構造非常巧妙,通過有限次簡單地算術運算就能求得結果,特別適合那些受儲存空間限制的演算法中使用。
此外,在這個部落格裡也有對編程之美裡五種解法的詳細分析,值得一讀。http://blog.csdn.net/shijiemazhenda/article/details/6785674