題目描述:請實現乙個函式,輸入乙個整數,輸入該數二進位制表示中1的個數。
例如:把9表示成二進位制是1001,有2位是1,所以輸入9,該函式輸出2
可能引起死迴圈的解法思路:先判斷整數二進位制數的最後一位是不是1,然後整數右移一位,此時原來處於倒數第二位就被移到最右邊了,再判斷是否是1。也就是,依次右移,如果最後一位是1,則得到1,如果是0,則得到0
這種思路中,待判斷的整數右移,而輔助判斷的數1是不動的
int numberof1(int n)
return
count;
}
這麼看起來上述**挺正常,但是暗藏殺機,就是當n為負數的時候,無論移動多少次,最高位填1,最後n的所有位將變為1,進入死迴圈……
把整數右移一位和把整數除以2在數學上是等價的,那麼上述**中把右移運算換成除以2可以嗎?
答案是否定的,因為除法的效率比移位運算要低得多,在實際程式設計中盡可能使用移位運算代替乘除法
常規解法思路:既然整數移動可能進入死迴圈,那麼換種思路,我們不移動待判斷的整數,而是去左移輔助判斷數1,那麼移動1次,2次,3次,……,輔助判斷數為10,100,1000,……,那麼通過&運算我們可以判斷整數的低x次位是否為1
經過32次移動後,輔助判斷數變為0,作為迴圈終止的條件
這邊有個小陷阱,就是n&flag的結果是多少證明該位為1呢?我們可以從flag下手,flag只有待判斷的這一位是1,如果整數中這一位為1,則計算的結果等於flag;如果整數為0,則計算的結果就是0
int numberof1(int n)
flag = falg << 1; //左移
}}
驚喜的解法這種解法就不是那麼常規的,而是很巧妙ԅ(¯㉨¯ԅ)
下面分析這種思路是怎麼來的~~~
分析乙個數減去1的情況。如果乙個整數不等於0,那麼該整數的二進位制中至少有一位是1。
1.假設最後一位為1,那麼減去1後,最後一位變為0,而其他所有位保持不變。也就是最後一位相當於進行了取反操作,由1變成了0。
2.最後一位不為1而是0的情況。如果該數的二進位制表示中最右邊1位於第m位,那麼-1後,第m位由1變為0,第m位之後的所有0變為1,第m位之前的所有位保持不變。
eg:1100 -1後,第二位變為0,後面的兩個0變為1,前面的1保持不變,所以得到結果1011
總結上述兩種情況,我們發現乙個數-1後,最右邊的1變為0,如果右邊還有0的話,都變為1,而它左邊的數都保持不變!!!
接下來就是見證奇蹟的時刻了!!!
把乙個整數和它減去1的結果做&運算,相當於把它最右邊的1變為0
eg:1100 & 1011 = 1000
基於這種思路,**如下:
int numberof1(int n)
return
count;
}
1.用一條語句判斷乙個整數是不是2的整數次方。
分析:乙個整數如果是2的整數次方,那麼二進位制表示中有且只有一位是1,而其他所有位都是0.根據前面的分析,我們將整數-1後再和它本身做&運算,那麼這個整數中唯一的1就會變成0
(a & (a-1)) == 0 ? 是:不是
2.輸入兩個整數m和n,計算需要改變m的二進位制表示中的多少位才能得到n
分析:首先求m^n,則計算的結果中有多少位為1,則表示m和n有多少位不同
舉一反三:把乙個整數減去1之後再和原來的整數做位與運算,得到的結果相當於把整數的二進位制表示中的最右邊乙個1變為0!
劍指Offer 面試題10 二進位制中1的個數
請實現乙個函式,輸入乙個整數,輸出該數二進位制表示中1的個數。例如把9表示成二進位制是1001,有2位是1.因此如果輸入9,該函式輸出2.注意 整數和負數以及0的區別,這是由儲存機制決定的。分析 將輸入的整數依次右移並與1相位與!源 如下 includeusing std cout using st...
劍指offer面試題10 二進位制中1的個數
題目 請實現乙個函式,輸入乙個整數,輸出該二進位制表示中1的個數。例如把9表示成二進位制是1001,有2位是1,因此如果輸入9,該函式輸出2。常規的解題思路 可以把n和1做與運算,如果結果為1,那麼n的最後一位為1,否則為0,然後n右移1位,再和1做與運算,直到判斷完n的所有位。int statis...
劍指offer 面試題10 二進位制中 1 的個數
題目 請實現乙個函式,輸入乙個整數,輸出該數二進位制表示中 1 的個數。例如把 9 表示成二進位制是 1001 有 2 位是 1,因此如果輸入 9,函式輸出 2.這個題本來我的思路是模擬十進位制的規則,設定乙個計數變數count,初始值為0。然後用給的整數數和2進行取餘操作,結果只有兩種可能 0或1...