数组异或操作

Posted 异次元的归来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数组异或操作相关的知识,希望对你有一定的参考价值。

这道题出自LeetCode,题目如下:

给你两个整数,nstart

数组 nums 定义为:nums[i] = start + 2*i(下标从 0 开始)且 n == nums.length

请返回 nums 中所有元素按位异或(XOR)后得到的结果。

示例 1:

输入: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:

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

示例 4:

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

这题其实利用到了一个数学公式,即:

\\[4i \\oplus (4i + 1) \\oplus (4i + 2) \\oplus (4i + 3) = 0 \\]

这个公式的推导也很简单,首先4i用二进制肯定可以表示为:

\\[4i = (xxxxx00)_2 \\]

类似地,其他3个数有:

\\[4i + 1 = (xxxxx01)_2 \\]

\\[4i + 2 = (xxxxx10)_2 \\]

\\[4i + 3 = (xxxxx11)_2 \\]

显然这4个数用二进制表示的位数是相同的,这里假设为n,那么前n-2位的表示也是完全相同的,因此4个数前n-2位异或之后的结果为0,而后两位分别为00,01,10,11,异或之后的结果也为0,所以最终得到的结果是0。

再回到题目,就是求:

\\[s \\oplus (s + 2) \\oplus ... \\oplus (s + 2(n - 1)) \\]

如果s为偶数,则可以直接提取2出来,得到:

\\[2(\\fracs2 \\oplus (\\fracs2 + 1) \\oplus ... \\oplus (\\fracs2 + n - 1)) \\]

如果s为奇数,则s,s + 2,...,s + 2(n - 1)都为奇数,可以表示为2i+1的形式。此时,我们注意到,异或结果的最后一位只取决于n的奇偶性,即n个1的异或值,如果n是奇数,那么最后一位就是1,反之如果n是偶数,则最后一位是0:

\\[2(\\lfloor\\fracs2\\rfloor \\oplus (\\lfloor\\fracs2\\rfloor + 1) \\oplus ... \\oplus (\\lfloor\\fracs2\\rfloor + n - 1)) + \\underbrace1\\oplus...\\oplus1_n \\]

那么实际上,我们可以把s为奇数和偶数得到的最终结果统一起来:

\\[\\begincases 2(\\lfloor\\fracs2\\rfloor \\oplus (\\lfloor\\fracs2\\rfloor + 1) \\oplus ... \\oplus (\\lfloor\\fracs2\\rfloor + n - 1)) + 1 & s和n均为奇数 \\\\ 2(\\lfloor\\fracs2\\rfloor \\oplus (\\lfloor\\fracs2\\rfloor + 1) \\oplus ... \\oplus (\\lfloor\\fracs2\\rfloor + n - 1)) & s和n不均为奇数 \\endcases \\]

我们令f(k)为从0异或到k的结果,则上面的式子可以化简为:

\\[\\begincases 2(f(\\lfloor\\fracs2\\rfloor + n - 1) \\oplus f(\\lfloor\\fracs2\\rfloor - 1)) + 1 & s和n均为奇数 \\\\ 2(f(\\lfloor\\fracs2\\rfloor + n - 1) \\oplus f(\\lfloor\\fracs2\\rfloor - 1)) & s和n不均为奇数 \\endcases \\]

现在,我们只需计算出f(k)即可。计算f(k)这时就用到前面提到的公式了,可以假设k = 4i, 4i + 1,4i + 2,4i + 3分别算出结果:

\\[\\begincases k & k = 4i \\\\ 1 & k = 4i + 1 \\\\ k + 1 & k = 4i + 2 \\\\ 0 & k = 4i + 3 \\endcases \\]

通过的代码如下:

class Solution 
public:
    int xorOperation(int n, int start) 
        int t = start >> 1;
        int res = helper(t - 1) ^ helper(t + n - 1);
        return (res << 1) | ((start & 0x1) & (n & 0x1));
    

    int helper(int t)
    
        int res = 0;
        switch(t & 0x3)
        
            case 0:
            res = t;
            break;

            case 1:
            res = 1;
            break;

            case 2:
            res = t + 1;
            break;

            case 3:
            res = 0;
        

        return res;
    
;

以上是关于数组异或操作的主要内容,如果未能解决你的问题,请参考以下文章

模拟1486. 数组异或操作

LeetCode1486. 数组异或操作(Java/c++ 暴力模拟)

LeetCode1486. 数组异或操作(Java/c++ 暴力模拟)

算法-数组异或操作(异或性质)

数组异或操作

LeetCode刷题1486-简单-数组异或操作