前言
有一天你要去面試,你信心滿滿,什么資料庫索引優化,jvm記憶體管理你都倒背如流,和你一起面試的還有一個看上去非常年輕像畢業的學生,你對他不屑一顧,見了面試官,你已經準備好了應付他的難題,只見面試官微微一笑:“請問現在有兩個int變數a,b,在不創建新變數的情況下,如何交換他們的值呢?”你有點懵逼,在紙上思前上去也毫無頭緒,難道不創建新變數還能交換值?只見那位學生微微一笑,提筆寫了幾下便交給面試官,只見面試官滿意的點點頭,而你卻尷尬地坐在原地(欲知后事請往下看)

目錄
前言
1.什么是位運算?
2.位運算有那些?
1.按位與&
2.按位或 |
3.異或^
前言解答:
4.取反運算子~與左右移運算子<< >>
2.位運算的技巧(干活)
1.干貨一:消去X二進制位的最后一位1
2.快速判斷是否是2的冪,
3.判斷一個數的二進制位有幾個1
4.找出重復陣列中,唯一一個不重復的數字
1.什么是位運算?
首先,我們要知道,我們地計算機存盤資料的形式都是二進制,就是所有的東西他都是轉化位二進制來保存,而二進制只有0和1兩個數字,我們的位運算就是在二進制的基礎上進行運算,它是一個二元運算子,就是對兩個資料進行操作,它是編程語言中最難最復雜的運算,所以專門用一篇文章講解,如果你還沒了解其他的運算,推薦看看我的這篇文章,非常適合新手
搞定編程語言所有基礎運算(圖解,詳細代碼)
2.位運算有那些?
1.按位與&
按位與的符號與我們邏輯運算子的邏輯與是一樣的,都是&,那&啥適合是按位與啥時候又是邏輯與呢?當我們&左右兩邊是整型變數時,它代表的是按位與,當左右兩邊是布林值時,它是邏輯與, 1&1=1 1&0=0 0&0=0
按位與&的邏輯是:如果兩個對應的二進制位都位1,則該位的結果值為1,否則為0
通過下圖能直觀的表示,

PS:我們知道在邏輯與中兩個true才是真的true,而在代碼中,往往1代表true,0代表false,所以兩個1代表真的1,這樣方便我們記憶,
2.按位或 |
按位或 | 符號與我們的的邏輯或符號相同,都是 | ,它的意思和我們的按位與相反,當左右兩邊只要有一個1則就為1,同理與上面的記法,或者你可以記成按位與&是都為1才為1,按位或|是都為0才為0, 1|1=1 1|0=1 0|0=0
同樣通過一個圖進行理解:
3.異或^
異或的符號是^,一般按鍵盤的shift加6,如果輸出的是……這樣則需要切換成英文鍵盤,異或的規則是兩個位數相同則位0,否則位1,因為它的名字帶一個異,而異的意思就是不同,說明如果是不同的話就說明是真的那就是1,都一樣的話那就是相同的,則是假的,記為0. 1^1=0 1^0 =1 0^0=0
前言解答:
你拿過紙上看了看,只見上面簡便地寫著:
public static void main(String[] args) {
int a=10;
int b=12;
a=a^b;
b=a^b;
a=a^b;
System.out.println(a);//12
System.out.println(b);//10
}
你驚訝地看著這短短地代碼,于是在紙上演算了起來
決議:我們可以發現,12和10異或得到一個數6,這個6和他們之間任何一個再次異或后可以得到另外一個,我們暫時將這個數6成為中轉數,即6再和12異或又得回了10,再和10異或又得回12,這三個數互相異或都會得到另外一個,這個性質就產生了前言的替換功能,沒有借助多余的變數,是不是很神奇
4.取反運算子~與左右移運算子<< >>
~
- 取反
- ~是一元運算子,用來對一個二進制數按位取反,即將0變1,將1
<<
- 左移
- 用來將一個數的各二進制位全部左移N位,右補0
>>
- 右移
- 將一個數的各二進制位右移N位,移到右端的低位被舍棄,對于無符號數, 高位補0
決議:這三個位運算用的較少,不做過多解釋,不過大家可以記住:一個整數左移一位會翻兩倍,移動兩位翻四倍,如10左移一位變20,移兩位變40,向右移動則相反,移動一位縮小一半,以此類推,
2.位運算的技巧(干活)
1.干貨一:消去X二進制位的最后一位1
x=1100(二進制形式)
x-1=1011
x&(x-1)=1000
x二進制的最后一位1變為了0
2.快速判斷是否是2的冪,
首先我們要明白,如果X是2的冪,如1,2,4,8,16等等
1.X>0
2.X的二進制的表示中只可能有一個1
如果我們利用x&(x-1)去掉x唯一的一個1,則得到結果肯定為0
如果,只要a是2的冪那么得到的結果肯定為0
public class Demo5 {
public static void main(String[] args) {
int a=16;
int b=a&(a-1);
System.out.println(b);//0
}
}
3.判斷一個數的二進制位有幾個1
這是一個高頻的考點,同理于上面,如果我們利用x&(x-1)可以去掉最后一位0,我們通過while回圈一直除去最后一位0,直到除完以后x變位0,則知道x的二進制位有幾位1,
代碼演示:
public class Demo5 {
public static void main(String[] args) {
int a=345897;
int count=0;
while (a!=0){
a=a&(a-1);
count++;
}
System.out.println(count);//9
}
}
4.找出重復陣列中,唯一一個不重復的數字
題目:在一個陣列中,每個數字都出現了兩次,只有一個陣列出現了一次,請找出這個數字
int[] arr={1,1,2,2,3,4,4,5,5,6,6}
我們通過異或的性質可以很清楚理解:x^x=0 x^0=x
public class Demo5 {
public static void main(String[] args) {
int[] arr={1,1,2,2,3,4,4,5,5,6,6};
int x=0;
for (int i = 0; i < arr.length; i++) {
x=arr[i]^x;
}
System.out.println(x);//3
}
}
第四個是LeetCode的題目,它還有升級版的題目,有興趣的可以去搜索,在這由于篇幅有限不做敘述,
水平有限,有錯誤請指出!多謝!

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/342261.html
標籤:其他
下一篇:【linux】——檔案系統
