位運算中異或的常見用法總結

2022-01-01 吳師兄學算法

點擊藍色「五分鐘學算法」關注我喲

加個「星標」,一起學算法

異或(^) 這個位操作運算符相信大家一定都不陌生,這個運算符可以用來解決很多普通算法解決不了的問題,而且位運算是直接對二進位碼做運算,相對普通的加減乘除運算符來說的話更加的高效,我們借著題目一起來看看。

對兩個輸入參數做加法運算,但是不能使用 「+」 運算符 。

解法思路

看到這樣的問題,能想到的只有位運算,問題是怎麼算?相信大家小學剛學習加法的時候,對於一下子不能得到答案的題,肯定會在草稿紙上列豎式,從右向左算,同一列對下來的數字相加如果超過 10,那麼肯定要在下面寫兩個數字相加後的個位數,然後往前進一位,下一位運算時就要加上這個進位,用這樣的方式直到最後算出結果。這題的思路也是一樣的,只不過有兩點不一樣,第一,10 進位變成了 2 進位,第二,我們不再是在草稿紙上列豎式,而是要寫成計算機看得懂的代碼,這就得藉助我們的位運算了,因為 2 進位表示的數中只會出現 0 和 1,你可以把這兩個數看成是 true 和 false,這樣更好理解,我們可以先通過異或塞選出不用進位的情況,然後再用與運算和左移運算計算出進位的情況,迭代更新出最後的結果。

參考代碼

public int plus(int a, int b) {
    int aTemp = 0, bTemp = 0;
    while (b != 0) {
        aTemp = a ^ b;
        bTemp = (a & b) << 1;
        a = aTemp;
        b = bTemp;
    }

    return a;
}

如何在不創建臨時變量的情況下進行交換兩個數?

解法思路

異或的常見應用,很簡單,但是注意思考角度從位出發,而不是數,這點很重要。

參考代碼

public void swap(int a, int b) {
    a ^= b; 
    b ^= a; 
    a ^= b; 
}


如果把 A 轉換成 B ,需要改變多少位?

解法思路

異或的簡單應用,兩個數做異或的結果就是兩個數差異所在,然後只需計算這個結果中有多少個 1 即可。

參考代碼

public int convertA2B(int A, int B) {
    int n = A ^ B;
    int count = 0;
    while (n != 0) {
        n = n & (n - 1); 
        count++;
    }

    return count;
}

LeetCode 第 136 號問題:給定一個非空整數數組,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。

解法思路

異或的三個點順下來,就可以很清楚地解這道題:

異或運算和乘法一樣,位置和運算順序不影響最後結果:a^b^c = b^c^a
兩個相同的數做異或運算結果為零:a^a = 0
任何數和零做異或結果還是這個數本身:a^0 = a

參考代碼

public int findOnce(int[] arr) {
    int result = 0;
    for (int i = 0; i < arr.length; ++i) {
        result ^= arr[i];
    }

    return result;
}


LeetCode 第 137  號問題:給定一個非空整數數組,除了某個元素只出現一次以外,其餘每個元素均出現了三次。找出那個只出現了一次的元素。

解法思路

這題的難點在於 3 次,如果把數組裡面的數字就當作數字本身來看的話,很難找到突破口;如果想到了位運算,那就要有一個概念就是位運算是基於位的,而不是基於數的,在這個問題中,所有的 bit 的出現次數只會有兩種情況,3*n,3*n + 1,這裡的 n 是任意整數,假設你遍歷數組,其實會有一個中間態就是 3*n + 2 存在,對於除這個數以外的其他數,過程大概是 3*n + 1 -> 3*n + 2 -> 3*n,我們只要記錄的就是 3*n + 1 和 3*n + 2的情況,因為 3*n 其實就是一個初始狀態(n=0),記不記錄和我們最後要返回的答案無關,而記錄 3*n + 2 是為了恢復一些 bit 從 3*n + 2 到 3*n

參考代碼

public int singleNumber(int[] nums) {
    int ones = 0, twos = 0;
    for (int i = 0; i < nums.length; ++i) {
        
        ones = (nums[i] ^ ones) & (~twos);
        
        twos = (nums[i] ^ twos) & (~ones);
    }

    return ones;
}


LeetCode 第 260  號問題:給定一個整數數組 nums,其中恰好有兩個元素只出現一次,其餘所有元素均出現兩次。找出只出現一次的那兩個元素。

解法思路

這題的主要難點是如何把兩個數給拆出來,如果直接運用異或算法,我們最後得到的結果是兩個數做異或的結果,關鍵點是如何基於這個異或的結果來找到這兩個數,有一點很重要的就是,異或的結果為 1 的點位只會出現在其中一個數中,我們可以用其中一個為 1 的點位作為判斷依據,這個點位存在的所有數在一起做異或,這個點位不存在的所有數一起做異或,這樣就把這個問題拆解成了兩個 problem 3。

參考代碼

public int[] singleNumber(int[] nums) {
    if (nums == null || nums.length == 0) {
        return new int[2];
    }

    int different = 0;
    for (int i : nums) {
        different ^= i;
    }

    different &= -different;
    int[] ans = {0, 0};
    for (int i : nums) {
        if ((different & i) == 0) {
            ans[0] ^= i;
        } else {
            ans[1] ^= i;
        }
    }

    return ans;
}

位運算相對其他的運算來說更加的高效,異或在位運算中的應用非常廣,但是這裡的難點是我們平時可能會忽視位運算,導致我們遇到一般的問題不會往位運算的方向去想,另外就是如果對二進位的運算不熟,我們也很難理解一些位運算的綜合操作,這裡提到了異或可以交換兩個數,做加法操作,還可以用來解決一些問題。

歡迎你來分享你對異或以及位運算的認識。

相關焦點

  • 有趣的 異或運算
    異或運算異或運算可以看作是沒有進位的加法,按位異或運算,相同為0,不同為1。0 ^ 0 = 00 ^ 1 = 11 ^ 0 = 11 ^ 1 = 0觀察運算結果我們發現,當與0做異或運算時,另一元值不變;而與1做異或運算時,另一元值取反。
  • 真實世界的異或運算
    對於底層開發來說,位運算是非常重要的一類操作。而對於位運算來說,最有意思的,應該就是異或運算(XOR)了。
  • C語言總結之異或運算的一些特性及巧妙應用
    1.一個數和自己做異或的結果是0。如果需要一個常數0,x86平臺的編譯器可能會生成這樣的指令:xorl %eax, %eax。不管eax寄存器裡的值原來是多少,做異或運算都能得到0,這條指令比同樣效果的movl $0, %eax指令快,直接對寄存器做位運算比生成一個立即數再傳送到寄存器要快一些。
  • Linux中Shell的算數運算符和位運算符用法筆記
    1、算數運算符算數運算符主要是加、減、乘、除、餘、冪等常見的算術運算,以及加等、減等、乘等、除等、餘等複合算術運算。2、位運算符位運算是基於內存中二進位數據的運算,也就是基於位的運算。常見的位運算有左移運算、右移運算、按位與、按位或、按位非、按位異或等運算。位元素的左移右移其實就是整數內存中的左右移動。左移<<,右移>>.
  • 異或運算法則和異或符號在multisim和word的輸入方法
    打開APP 異或運算法則和異或符號在multisim和word的輸入方法 佚名 發表於 2017-11-28 11:40:51
  • Leetcode刷題 異或運算
    解決方案在解題之前,我們先複習下異或運算。任何數和 0 做異或運算,結果仍然是原來的數,即 a⊕0=a。任何數和其自身做異或運算,結果是 0,即a⊕a=0。異或運算滿足交換律和結合律,即 a⊕b⊕a=b⊕a⊕a=b⊕(a⊕a)=b⊕0=b。也就是說,滿足AABBC,無論打亂什麼順序,A^A^B^B^C = C 都是滿足的。
  • 你可能不知道的位運算技巧
    本篇的內容為位運算的介紹和一些比較經典的位運算問題進行介紹分析,當然,位運算這麼牛,後面肯定還是要歸納總結的。認識位運算什麼是位運算?程序中的所有數在計算機內存中都是以二進位的形式儲存的。位位運算就是直接對整數在內存中的二進位位進行操作。位運算就是直接操作二進位數,那麼有哪些種類的位運算呢?常見的運算符有與(&)、或(|)、異或(^)、取反(~)、左移(<<)、右移(>>是帶符號右移 >>>無符號右移動)。下面來細看看每一種位運算的規則。
  • C語言中的"異或^"操作可以很秀~
    ,第一次遇到的時候感覺挺有意思的,畢竟對於if_else專家而言,這些「|」、「&」等運算符是再熟悉不過了.但異或運算符估計很多朋友只在C語言初學運算符的章節背過一些性質罷了,所以今天bug菌把異或的一些小技巧分享一下,進一下階~一句話總結異或運算 : "相同為0,相異為1",如下: A XOR B    result   0  ^  0  =  0
  • 一文讀懂位運算
    位運算就是直接對整數在二進位進行計算操作。作為一名程式設計師掌握位運算的基本使用是很重要的,而對於算法程式設計師來說,位運算的靈活使用能夠更靈活高效的解決很多問題。按位異或(^)參加運算的兩個數按二進位進行異或運算。0^0=00^1=11^1=0用途:翻轉指定位如要將X=0101 1010的低4位翻轉為0101,則只需和Y=0000 1111進行異或運行,X^Y=0101 0101 。
  • 程式設計師使用"位運算"裝逼指南
    按位異或(^)按位異或運算法則可以概括成「相同則假,不同則真」,在0和1之間的運算,有以下形式:1 | 1 = 01 | 0 = 10 | 0 = 0仍然還是數字5與數字a = a^b #(1)b = a^b #(2)a = a^b #(3)如果你沒接觸過位運算,對於這三行代碼肯定很懵,讀懂這三行代碼你還需要知道按位異或的幾個性質:1.按位異或滿足交換律,即a ^ b = b ^ a2.按位異或滿足結合律,即(a^b)^c=a^(b^c
  • 大腦只需單個神經元就可進行異或運算,Science新研究揭冰山一角
    邊策 賴可 發自 凹非寺量子位 報導 | 公眾號 QbitAI在機器學習中,異或(XOR)這樣的非線性問題一直需要多層神經網絡來解決。科學家一直以為,即使在人類大腦中,XOR運算也需要多層神經元網絡才能計算。
  • 巧妙運用C語言位運算
    以上用法都先要設計好一個常數,該常數只有需要的位是1,不需要的位是0。用它與指定的位串信息按位與。(2)按位或運算符(|)按位或運算將兩個運算分量的對應位按位遵照以下規則進行計算: 0 | 0 = 0, 0 | 1 = 1, 1 | 0 = 1, 1 | 1 = 1即只要有1個是1的位,結果為1,否則為0。例如,023 | 035 結果為037。
  • 好玩的位運算
    進行枚舉通過移位操作,可以創建互不幹擾(比特位置不一樣)的變量type1 = 1type2 = 1 << 1type3 = 1 << 2type4 = 1 << 5最常見的例子,莫過於在LInux系統中的權限信息了,一般說的777、711、700這些都是位運算運用的結果,由於Linux
  • 大腦只需單個神經元就可進行XOR異或運算,Science新研究揭開冰山一角,引發熱議
    邊策 賴可 發自 凹非寺量子位 報導 | 公眾號 QbitAI在機器學習中,異或(XOR)這樣的非線性問題一直需要多層神經網絡來解決
  • 位運算-補碼那些事
    原碼:計算機中對數字的二進位定點表示方法,這種表示方法在數字前面加上一個符號位,「1」代表這個數是負數,「0」代表這個數是正數,除符號位之外,其餘位表示該數字的值。(注意:如果明確定義為無符號整數,那麼將不存在符號位,本文主要講述的是有符號整數的情況)先舉一個簡單的例子:假設一個數在內存中佔8個比特位,那麼在內存中一個數就用八個二進位位來表示,「1」用原碼來表示就是 00000001,「-1」用原碼來表示就是10000001。
  • [洛穀日報第79期]二進位與位運算
    反碼:正數的反碼與其原碼相同;負數的反碼是對其原碼逐位取反,但符號位除外。補碼:正數的補碼與原碼相同,負數的補碼是其對應正數二進位所有位取反後加1。在計算機中通常使用補碼進行儲存。位運算是計算機中最簡潔的運算,並且具有很好用的性質,而且用起來還比較快。總而言之,位運算是十分實用的。「<<」 「>>」 運算首先,在這裡這東西跟 cin cout 沒有什麼關係。
  • [GO語言基礎] 四.算術運算、邏輯運算、賦值運算、位運算及編程練習
    這篇文章將介紹運算,包括算術運算、邏輯運算、賦值運算、位運算及編程練習。 這系列文章入門部分將參考「尚矽谷」韓順平老師的視頻和書籍《GO高級編程》,詳見參考文獻,並結合作者多年的編程經驗進行學習和豐富,且看且珍惜!
  • java基礎案例之java語言運算符算術賦值比較邏輯三元和位運算
    位運算符:對二進位進行運算;及將數字轉換成2進位後再進行運算。位運算位運算,左移,右移,無符號右移。位運算速算位運算中的與或異或反碼,位運算中的與或異或反碼下面分享下兩種思路互換變量值需求:對兩個變量值互換(需要用到第三變量)
  • ​LeetCode刷題實戰421:數組中兩個數的最大異或值
    今天和大家聊的問題叫做 數組中兩個數的最大異或值,我們先來看題面:https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/Given an integer array nums, return the maximum result of nums[i] XOR nums[j
  • C語言學習-15 位運算
    2 位運算操作符位運算符含義&按位與|按位或~取反^按位異或<<左移>>右移2.1 「與」運算符按位「與」運算符「&」是雙目運算符,功能是使參與運算的兩數各對應的二進位相「與」。只有對應的兩個二進位均為1時,結果才為1,否則為0。