数组异或操作

数组异或操作

这道题出自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

这题其实利用到了一个数学公式,即:
4 i ⊕ ( 4 i + 1 ) ⊕ ( 4 i + 2 ) ⊕ ( 4 i + 3 ) = 0 4i \oplus (4i + 1) \oplus (4i + 2) \oplus (4i + 3) = 0 4i(4i+1)(4i+2)(4i+3)=0
这个公式的推导也很简单,首先4i用二进制肯定可以表示为:
4 i = ( x x x x x 00 ) 2 4i = (xxxxx00)_2 4i=(xxxxx00)2
类似地,其他3个数有:
4 i + 1 = ( x x x x x 01 ) 2 4i + 1 = (xxxxx01)_2 4i+1=(xxxxx01)2

4 i + 2 = ( x x x x x 10 ) 2 4i + 2 = (xxxxx10)_2 4i+2=(xxxxx10)2

4 i + 3 = ( x x x x x 11 ) 2 4i + 3 = (xxxxx11)_2 4i+3=(xxxxx11)2

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

再回到题目,就是求:
s ⊕ ( s + 2 ) ⊕ . . . ⊕ ( s + 2 ( n − 1 ) ) s \oplus (s + 2) \oplus ... \oplus (s + 2(n - 1)) s(s+2)...(s+2(n1))
如果s为偶数,则可以直接提取2出来,得到:
2 ( s 2 ⊕ ( s 2 + 1 ) ⊕ . . . ⊕ ( s 2 + n − 1 ) ) 2(\frac{s}{2} \oplus (\frac{s}{2} + 1) \oplus ... \oplus (\frac{s}{2} + n - 1)) 2(2s(2s+1)...(2s+n1))
如果s为奇数,则s,s + 2,…,s + 2(n - 1)都为奇数,可以表示为2i+1的形式。此时,我们注意到,异或结果的最后一位只取决于n的奇偶性,即n个1的异或值,如果n是奇数,那么最后一位就是1,反之如果n是偶数,则最后一位是0:
2 ( ⌊ s 2 ⌋ ⊕ ( ⌊ s 2 ⌋ + 1 ) ⊕ . . . ⊕ ( ⌊ s 2 ⌋ + n − 1 ) ) + 1 ⊕ . . . ⊕ 1 ⏟ n 2(\lfloor\frac{s}{2}\rfloor \oplus (\lfloor\frac{s}{2}\rfloor + 1) \oplus ... \oplus (\lfloor\frac{s}{2}\rfloor + n - 1)) + \underbrace{1\oplus...\oplus1}_{n} 2(2s(2s+1)...(2s+n1))+n 1...1
那么实际上,我们可以把s为奇数和偶数得到的最终结果统一起来:
{ 2 ( ⌊ s 2 ⌋ ⊕ ( ⌊ s 2 ⌋ + 1 ) ⊕ . . . ⊕ ( ⌊ s 2 ⌋ + n − 1 ) ) + 1 s 和 n 均 为 奇 数 2 ( ⌊ s 2 ⌋ ⊕ ( ⌊ s 2 ⌋ + 1 ) ⊕ . . . ⊕ ( ⌊ s 2 ⌋ + n − 1 ) ) s 和 n 不 均 为 奇 数 \begin{cases} 2(\lfloor\frac{s}{2}\rfloor \oplus (\lfloor\frac{s}{2}\rfloor + 1) \oplus ... \oplus (\lfloor\frac{s}{2}\rfloor + n - 1)) + 1 & s和n均为奇数 \\ 2(\lfloor\frac{s}{2}\rfloor \oplus (\lfloor\frac{s}{2}\rfloor + 1) \oplus ... \oplus (\lfloor\frac{s}{2}\rfloor + n - 1)) & s和n不均为奇数 \end{cases} {2(2s(2s+1)...(2s+n1))+12(2s(2s+1)...(2s+n1))snsn
我们令f(k)为从0异或到k的结果,则上面的式子可以化简为:
{ 2 ( f ( ⌊ s 2 ⌋ + n − 1 ) ⊕ f ( ⌊ s 2 ⌋ − 1 ) ) + 1 s 和 n 均 为 奇 数 2 ( f ( ⌊ s 2 ⌋ + n − 1 ) ⊕ f ( ⌊ s 2 ⌋ − 1 ) ) s 和 n 不 均 为 奇 数 \begin{cases} 2(f(\lfloor\frac{s}{2}\rfloor + n - 1) \oplus f(\lfloor\frac{s}{2}\rfloor - 1)) + 1 & s和n均为奇数 \\ 2(f(\lfloor\frac{s}{2}\rfloor + n - 1) \oplus f(\lfloor\frac{s}{2}\rfloor - 1)) & s和n不均为奇数 \end{cases} {2(f(2s+n1)f(2s1))+12(f(2s+n1)f(2s1))snsn
现在,我们只需计算出f(k)即可。计算f(k)这时就用到前面提到的公式了,可以假设k = 4i, 4i + 1,4i + 2,4i + 3分别算出结果:

{ k k = 4 i 1 k = 4 i + 1 k + 1 k = 4 i + 2 0 k = 4 i + 3 \begin{cases}k & k = 4i \\ 1 & k = 4i + 1 \\ k + 1 & k = 4i + 2 \\ 0 & k = 4i + 3 \end{cases} k1k+10k=4ik=4i+1k=4i+2k=4i+3

通过的代码如下:

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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值