位運算
位運算是把數字用二進制表示以後,對每一位上的0或者1的運算。理解位運算的第一步是理解二進制。二進制是指數字每一位都是0或者1,如十進制的2轉換爲二進制以後是10,而十進制的10轉換爲二進制以後是1010。在程序員圈子裏有一個流傳了好久的笑話,說世界上有10種人,一種人知道二進制,另外一種人不知道二進制。 下面是幾個常見的關於位運算的算法題:
基本位運算
位運算總共只有5種運算:與&,或|,異或^,左移<<,右移>>.
與,或,異或的運算規則:程序員
左移,右移運算規則:
左移運算m < < n表示把m左移n位,左移n位時,最左邊的n位被丟棄,同時在最右邊補上n個0.如:面試
00001010 << 2 = 00101000 10001010 << 3 = 01010000
右移運算m > > n 表示把m右移n位,右移n位時,最右邊的n位被丟棄,最左邊根據該數字的類型決定,若是該數是一個無符號數值,則用0填補最左邊的n位。若是該數是一個有符號數值,用數字的符號位填補最左邊的n位,也就是若是該數是正數,則用0填補最左邊的n位。若是該數是負數,則用1填補最左邊的n位(補充知識點:一個有符號的數字,它的二進制最高位若是是1,則代表該數字爲負數,若是是0則爲正數)。如對有符號8位數字進行右移:算法
00001010 >> 2 = 00000010 10001010 >> 3 = 11110001
整數的二進制中1的個數
題目:實現一個函數,輸入一個整數,輸出該數二進制表示中1的個數。如輸入9,9的二進制表示是1001,有兩個1,所以輸入9該函數返回2.數組
public int count (int n) { int res = 0; while (n!=0) { n = n&(n-1);//該語句的做用是將二進制數中最右邊的1變爲0 res++; } return res; }
不用額外變量交換兩個整數的值
只須要以下三行代碼:數據結構
a = a^b; b = a^b; a = a^b;
如何判斷一個整數是否是2的整數次方
若是一個整數是2的整數次方,則它的二進制表示中應該只有一位是1,其它位都爲0,如 2 的二進制表示爲0010,4的二進制表示爲0100。因此把這個整數減去1,再與自身做&運算(如求整數中1的個數的方法),這樣該整數中惟一的一個1就變爲0。函數
public boolean isIntPower(int n) { return (n&(n-1)) == 0; }
兩個整數m和n,計算須要改變m二進制表示中多少位,才能夠獲得n.
如4的二進制表示爲0100,2的二進制表示爲0010,4須要改變2位才能夠變成2.分兩步求解:第一步求兩個整數的異或,第二步統計異或結果中1的個數。學習
public int count (int m,int n) { int a = m^n; int res = 0; while (a!=0) { a = a&(a-1);//該語句的做用是將二進制數中最右邊的1變爲0 res++; } return res; }
在其餘數都出現偶數次的數組中找出出現奇數次的數
給定一個數組arr,其中只有一個數出現了奇數次,其餘數都出現了偶數次,打印這個數。spa
public void getOddTimesNumber(int[] arr) { int eO = 0; for (int cur : arr) { eO = eO ^ cur; } System.out.println(eO+""); }
學習算法的記錄和整理,若有錯誤或意見請幫忙指出,之後會持續更新。。。。code
參考書籍:
《程序員代碼面試指南:IT名企算法與數據結構題目最優解》—左程雲
《劍指Offer》 —何海濤blog