算法(6)-數組異或操做(異或性質)

算法(6)-數組異或操做

1486. 數組異或操做java

力扣官方題解L6算法

1. 題目

1486. 數組異或操做

難度簡單83數組

給你兩個整數,nstart函數

數組 nums 定義爲:nums[i] = start + 2*i(下標從 0 開始)且 n == nums.lengthcode

請返回 nums 中全部元素按位異或(XOR)後獲得的結果。leetcode

示例 1:get

輸入:n = 5, start = 0
輸出:8
解釋:數組 nums 爲 [0, 2, 4, 6, 8],其中 (0 ^ 2 ^ 4 ^ 6 ^ 8) = 8 。
     "^" 爲按位異或 XOR 運算符。

示例 2:數學

輸入:n = 4, start = 3
輸出:8
解釋:數組 nums 爲 [3, 5, 7, 9],其中 (3 ^ 5 ^ 7 ^ 9) = 8.

示例 3:it

輸入:n = 1, start = 7
輸出:7

示例 4:io

輸入:n = 10, start = 5
輸出:2

提示:

  • 1 <= n <= 1000
  • 0 <= start <= 1000
  • n == nums.length

2. 題解

2.1 方法一:模擬

思路

按照題意模擬便可:

代碼

class Solution {
    public int xorOperation(int n, int start) {
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans ^= (start + i * 2);
        }
        return ans;
    }
}

複雜度分析

  • 時間複雜度:O(n)。這裏用一重循環對 n 個數字進行異或。
  • 空間複雜度:O(1)。這裏只是用了常量級別的輔助空間。

2.2 方法二:數學

記 ⊕ 爲異或運算,異或運算知足如下性質:

  1. xx=0;
  2. xy=yx(交換律);
  3. (xy)⊕z=x⊕(yz)(結合律);
  4. xyy=x(自反性);
  5. iZ,有 4i⊕(4i+1)⊕(4i+2)⊕(4i+3)=0。

在本題中,咱們須要計算 start⊕(start+2i)⊕(start+4i)⊕⋯⊕(start+2(n−1))。

觀察公式能夠知道,這些數的奇偶性質相同,所以它們的二進制表示中的最低位或者均爲 1,或者均爲 0。因而咱們能夠把參與運算的數的二進制位的最低位提取出來單獨處理。當且僅當 start 爲奇數,且 n 也爲奇數時,結果的二進制位的最低位才爲 1。

此時咱們能夠將公式轉化爲 (s⊕(s+1)⊕(s+2)⊕⋯⊕(s+n−1))×2+e,其中 s=start/2,e 表示運算結果的最低位。即咱們單獨處理最低位,而捨去最低位後的數列恰成爲一串連續的整數。

這樣咱們能夠描述一個函數 sumXor(x),表示0⊕1⊕2⊕⋯⊕x。利用異或運算的性質 5,咱們能夠將計算該函數的複雜度下降到 O(1),由於以 4i 爲開頭的連續四個整數異或的結果爲 0,因此 sumXor(x) 能夠被表示爲:

$$ \text{sumXor}(x)= \begin{cases} x,& x=4k,k\in Z\\ (x-1) \oplus x,& x=4k+1,k\in Z\\ (x-2) \oplus (x-1) \oplus x,& x=4k+2,k\in Z\\ (x-3) \oplus (x-2) \oplus (x-1) \oplus x,& x=4k+3,k\in Z\\ \end{cases} $$

咱們能夠進一步化簡該式:

$$ \text{sumXor}(x)= \begin{cases} x,& x=4k,k\in Z\\ 1,& x=4k+1,k\in Z\\ x+1,& x=4k+2,k\in Z\\ 0,& x=4k+3,k\in Z\\ \end{cases} $$

這樣最後的結果便可表示爲:

$$ (\text{sumXor}(s-1) \oplus \text{sumXor}(s+n-1))\times 2 + e) $$

代碼

class Solution {
    public int xorOperation(int n, int start) {
        int s = start >> 1, e = n & start & 1;
        int ret = sumXor(s - 1) ^ sumXor(s + n - 1);
        return ret << 1 | e;
    }

    public int sumXor(int x) {
        if (x % 4 == 0) {
            return x;
        }
        if (x % 4 == 1) {
            return 1;
        }
        if (x % 4 == 2) {
            return x + 1;
        }
        return 0;
    }
}

複雜度分析

  • 時間複雜度:O(1)。咱們只須要常數的時間計算出結果。
  • 空間複雜度:O(1)。咱們只須要常數的空間保存若干變量。

3. 思考

  1. 首先,下面的計算公式中前兩項,運用了前綴和的思路,即

    $$ \begin{cases} \text{sumXor}(s-1)\quad\quad\ = 0 \oplus 1 \oplus 2 \oplus ··· \oplus {(s-2)} \oplus {(s-1)}\\ \text{sumXor}(s+n-1)) = 0 \oplus 1 \oplus 2 \oplus ··· \oplus {(s-2)} \oplus {(s-1)} \oplus {(s)} \oplus {(s+1)} \oplus ···\oplus {(s+n-2)}\oplus {(s+n-1)} \end{cases} $$

    故,按照性質1,這兩項進行異或時,至關於作前綴和的減法,即:

$$ \text{sumXor}(s-1) \oplus \text{sumXor}(s+n-1) =[0 \oplus 1 \oplus ··· \oplus {(s-1)}] \oplus [0 \oplus 1 \oplus ··· \oplus {(s-1)} \oplus {s} \oplus ···\oplus {(s+n-2)}\oplus {(s+n-1)}] \\ \quad\quad \quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad =[0 \oplus 0 \oplus 1 \oplus 1 \oplus ··· \oplus {(s-1)} \oplus {(s-1)}] \oplus {s} \oplus ···\oplus {(s+n-2)}\oplus {(s+n-1)} \\ \quad\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad\quad \quad\quad = {s} \oplus {(s+1)} \oplus···\oplus {(s+n-2)}\oplus {(s+n-1)} $$

  1. 對於 e 計算,則是出於如下緣由點:

    對於二進制數,由於每次都是給 start 加上 2 的倍數,因此,最後獲得的數組中全部數字二進制的最後一位一直是不變的,即 start 若是是偶數,則數組中全部數都是偶數,最後一位全爲0,若是是奇數,則數組中全部數都是奇數,最後一位全爲1。

    所以可知,只有 start爲奇數,而且n爲奇數時,e的最後一位才能爲1,其餘狀況全爲0。

    又由於咱們只須要最後一位,因此還要按位與上1,即:n & start & 1

  2. 綜合思考1思考2,咱們能夠把題目作以推廣,即:

    給你三個整數,nstartk

    數組 nums 定義爲:nums[i] = start + k*i(i從0開始,k=2^m(m>=1))且 n == nums.length

    請返回 nums 中全部元素按位異或(XOR)後獲得的結果。

    題目的解法和上面的同樣,結果 result 能夠表示爲:

    $$ result =\text{sumXor}(s-1) \oplus \text{sumXor}(s+n-1))\times k + e \\ 其中 s=\lfloor \frac{\textit{start}}{2} \rfloor,e=(start \% k) \oplus (start \% k) \oplus ···\oplus(start \% k)\oplus(start \% k) $$

    而上面的e等於n個start對k的餘數異或,可參照思考2,分別對倒數第一位,倒數第二位,一直到倒數第m位(k=2^m(m>=1))求解,再按位與便可。

相關文章
相關標籤/搜索