详解位运算解题套路
1.位運算解題技巧
1、使用 x & 1 == 1 判斷奇偶數。(注意,一些編輯器底層會把用%判斷奇偶數的代碼,自動優化成位運算)
2、不使用第三個數,交換兩個數。x = x ^ y , y = x ^ y , x = x ^ y。(早些年喜歡問到,現在如果誰再問,大家會覺得很low)
3、兩個相同的數異或的結果是 0,一個數和 0 異或的結果是它本身。(對于找數這塊,異或往往有一些別樣的用處。)
4、x & (x - 1) ,可以將最右邊的 1 設置為 0。(這個技巧可以用來檢測 2的冪,或者檢測一個整數二進制中 1 的個數,又或者別人問你一個數變成另一個數其中改變了多少個bit位,統統都是它)
5、異或可以被當做無進位加法使用,與操作可以用來獲取進位。
6、i+(~i)=-1,i 取反再與 i 相加,相當于把所有二進制位設為1,其十進制結果為-1。
7、對于int32而言,使用 n >> 31取得 n 的正負號。并且可以通過 (n ^ (n >> 31)) - (n >> 31) 來得到絕對值。(n為正,n >> 31 的所有位等于0。若n為負數,n >> 31 的所有位等于1,其值等于-1)
8、使用 (x ^ y) >= 0 來判斷符號是否相同。(如果兩個數都是正數,則二進制的第一位均為0,x ^ y=0;如果兩個數都是負數,則二進制的第一位均為1;x ^ y=0 如果兩個數符號相反,則二進制的第一位相反,x ^ y=1。有0的情況例外,^相同得0,不同得1)
9.a-b結果的符號(int 類型),可以用(a-b)>>31得出,-1則是為負,0為正數
2.異或(^)與與(&)左移(<<)做加法運算
無進位和 與 異或運算 規律相同,進位 和 與運算 規律相同
那么每異或一次,相當于求一次兩數無進位和,每做一次與運算加左移,相當于求出所有進位的和,再與第一次異或的結果再次異或,如此循環,當沒有進位時即進位和為0時,代表求出最終結果
C++代碼
class Solution { public:int add(int a, int b) {while(b!=0){int c=(unsigned int)(a&b)<<1;a=a^b;b=c;}return a;} };3.異或(^)的妙用
那么如果把一個數組的所有元素全部異或一遍,那么最終得到的結果是兩個不重復值的異或結果,又由于異或是相同得0不同得1,我們找到異或結果從低位到高位的第個位1(哪一位1都無所謂),那么異或的兩個值,一個此位置為0,一個此位置為1,就可以把數組的元素分為兩組,這個時候,此位置為1的數據與a異或,為0的數據與b異或,最終a和b就是兩個我們需要的數據(其余數據的異或會得到0,因為其余數字都出現兩次)
4.0x55555555與0xaaaaaaaa的妙用
0xaaaaaaaa = 10101010101010101010101010101010 (偶數位為1,奇數位為0)
0x55555555 = 1010101010101010101010101010101 (偶數位為0,奇數位為1)
5.n&(n-1)的妙用
任何一個是2的冪次方的數,它都是最高位(代表數值的位)是1,后面的數字全0,那么這個數減1與這個數進行位于運算一定為0,即:
class Solution { public:bool isPowerOfTwo(int n) {return (n>0)&&(n&(n-1))==0;} };n&(n-1)每進行一輪都會把當前數值部分(也就是n)最低位的1變成0。比如:數值11轉化成二進制有三個1,那么每進行一次n=n&(n-1)就會消去當前n最低位的1
class Solution { public:int hammingWeight(uint32_t n) {int cnt=0;while(n){n&=(n-1);++cnt;}return cnt; } };總結
- 上一篇: 为啥地址线是20根则存储单元个数为2的2
- 下一篇: 三种集中式总线判优控制