位運算是把數字用二進位制表示後,對每一位上的0或者1的運算。
面試題15:二進位制中1的個數。請實現乙個函式,輸入乙個整數,輸出該數二進位制表示(即補碼表示)中1的個數。例如,把9表示成二進位制是1001,有2位是1。因此,如果輸入9,則函式輸出2。
很快我們得到乙個思路,先判斷該數二進位制表示中右邊一位是不是1,接著把輸入的整數右移一位,此時原來處於從右邊數起的第二位被移到最右邊了,再判斷是不是1,重複以上步驟直到該數變為0。判斷最右邊一位是否是1,只需要把要判斷的數和1相與,結果為1則表示最右邊一位為1,否則為0。把整數右移一位和把整數除以2是等價的,但移位運算的效率比除法高得多,用到除法的地方最好用移位運算代替:
#include
using
namespace std;
intnumberof1
(int num)
num >>=1;
}return count;
}int
main()
但這種解法有乙個問題,當輸入的數字為負數時,大多數編譯器在右移時左邊會複製符號位,那麼最終迴圈到整個數的二進位制位全為1,陷入死迴圈。
為了避免死迴圈,我們可以不右移輸入的數字n,首先把n與1做與運算,判斷n的最低位是不是1,接著把1左移一位得到2,再與n與運算判斷次低位是不是1,重複以上過程,直到1變為0:
#include
using
namespace std;
intnumberof1
(int num)
flag <<=1;
}return count;
}int
main()
這個解法中,迴圈的次數等於二進位制的位數,32位整數迴圈32次,接下來是一種有幾個1迴圈幾次的解法。
我們先分析將乙個數減去1的情況。如果乙個整數不等於0,那麼該整數的二進位制表示中至少有一位是1,先假設這個數的最右邊的值為1,那麼減去1時,最後一位變成0,而其他所有位都保持不變,相當於最後一位做了取反操作,由1變為了0。接下來假設最後一位不是1而是0時的情況,如果該數的二進位制表示中最右邊的1位於第m位,那麼減去1時,第m位由1變為0,m位之後的所有0變為1,m位之前的所有位都保持不變。我們可以發現,當把乙個數減去1的結果與這個數做與運算,會把這個數的最右邊的1變為0,如1100,減去1之後變為1011,相與結果為1000。那麼這個數中有幾個1,重複幾次此操作即可:
#include
using
namespace std;
intnumberof1
(int num)
return count;
}int
main()
相關題目:
1.一條語句判斷乙個整數是否為2的整次方,如果是,那麼它的二進位制表示中只有乙個1,根據前面分析,把這個整數減去1之後與它自己相與結果為0就是2的整數次方。
2.輸入兩個整數m和n,計算需要改變m的二進位制表示中的多少位才能得到n。比如10的二進位制位為1010,13的二進位制位為1101,則需要改變三個二進位制位。求解這個問題可分為兩步,第一步求出這兩個值的異或,最後找異或結果中有幾個1。
把乙個整數減去1之後結果與原來的整數做位與運算,得到的結果相當於把最右邊的1變成0。
劍指Offer(五) 位運算
寫乙個函式,求兩個整數之和,要求在函式體內不得使用 四則運算符號。位運算 coding utf 8 class solution def add self,num1,num2 write code here a,b num1,num2 while b 0 a,b a b,a b 1 a 0xffff...
位運算劍指offer經典題
40.乙個整型陣列裡除了兩個數字之外,其他的數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。陣列裡包含了兩個只出現一次的數字,那麼所有數字依次異或的結果就是這兩個只出現一次的數字的異或結果。我們要想辦法利用這個異或結果,把陣列分為兩個子陣列,乙個子陣列包含乙個只出現一次的數字,另乙個陣列包含另...
劍指offer學習筆記
筆記主要記錄方法和知識點 知識點1 負數與補碼 乙個參考 知識點2 移位操作 右移 變小 按位 操作 知識點3 0xffffffff表示32位 1 o logn 的方法 非遞迴的快速冪,用到二進位制表示。在迴圈內注意base base。兩個指標等間距一起走。想明白斷開鍊錶這個事情,相當於操作是在原有...