leetcode 1486. 数组异或操作 https://leetcode.cn/problems/xor-operation-in-an-array/

1486. 数组异或操作

题目描述#

给你两个整数,n 和 start 。

数组 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

数据范围#

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

分析#

第一种解法#

第一种解法是模拟,直接用for循环遍历模拟异或操作

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

        return ans;
    }

第二种解法 数学#

第一种解法中在当前题目所给的数据范围是可以的,一旦数据范围出到108,大概率会发生TLE超时,事实上,本题存在数据规律解法。

异或运算满足以下性质:

  1. xx=0

  2. xy=yx

  3. (xy)z=x(yz)

  4. xyy=x

  5. iZ4i(4i+1)(4i+2)(4i+3)=0

在本题中,我们需要计算的式子为:

start(start+2)(start+4)...(start+2(n1))

观察原式,可以发现,每一个数列中的数奇偶性都是一样的,那么可以得知,数列中的每一个数的最低位或者都为0,或者都为1,由此可以把数列里每一个数的二进制位的最低位都单独拎出来处理,可以得到以下几种情况:

  1. n为奇数,start为偶数:偶数个奇数做异或,计算结果二进制最低位为0
  2. n为奇数,start为奇数:start-1个奇数做异或,计算结果二进制最低位为0,在和奇数做异或,最终结果的二进制最低位为1
  3. n为偶数,start为偶数:偶数个偶数做异或,计算结果二进制最低位为0
  4. n为偶数,start为奇数:start-1个偶数做异或,计算结果二进制最低位为0,在和偶数做异或,最终结果的二进制最低位为0

可以得到,当且仅当start和n都为奇数时,计算结果二进制的最低为才为1,即

=nstart1

继续观察该式子可以发现,式子的差值为2,第五条性质需要数是连续的,结合数列的奇偶性,考虑把计算式子除以2(右移一位),即

12start(12start+1)(12start+2)...(12start+n1)

l令s=12start,可得一个连续的数列

s(s+1)(s+2)...(s+n1)

综上,最终所求式子需要在连续数列的基础上乘以2(左移一位)并把单独处理的最低位结果加回去,e表示最低位

(s(s+1)(s+2)...(s+n1))2+e

这里需要注意:

异或运算中每一位都是单独运算,右移不会影响移动部分的计算结果

对一串连续的整数数列,如012...x,根据第五条性质,可以得到

  1. 当x = 4k时,数列长度为x+1,即4k+1,根据性质5可得每四个数字的异或计算结果为0,所以只剩下一个x,即0x=x
  2. 当x = 4k + 1时,根据性质5,此时还剩下两位,即x(x1)0,即(4k+1)4k,观察可以看出两个数仅仅是最后一位不同,例如4和5、8和9,异或结果为1;
  3. 当x = 4k + 2时,即x(x1)(x2)0==>x1==>(4k+2)1==>4k+2+1==>x+1,从另一个角度看,x%4 == 2说明x一定是个偶数,偶数的最低位是0,因为4k(4k+1)=1,并且n^1 = n+1,所以x(x1)(x2)0==>x1==>x+1
  4. 当x = 4k + 3时,即x(x1)(x2)(x3)0,由以上推断可以得知(x1)(x2)(x3)=x+1,x+1刚好等于当前的x,即xx=0,所以结果为0。

综上,可得表示012...x的函数sumXor(x)

sumXor(x)={x,x=4k,kZ(x1)x,x=4k+1,kZ(x2)(x1)x,x=4k+2,kZ(x3)(x2)(x1)x,x=4k+3,kZ

进一步化简,可得

sumXor(x)={x,x=4k,kZ1,x=4k+1,kZx+1,x=4k+2,kZ0,x=4k+3,kZ

根据异或运算第四条性质xyy=x,假设y=sumXor(s1),表示数列从0到s-1的异或结果,x是我们需要的结果,即数列从s到s+n-1的异或结果

显然,xy=sumXor(s+n1),所以xyy=sumXor(s+n1)sumXor(s1)

这样最后的结果可以表示为

(sumXor(s+n1)sumXor(s1))2+e

代码#

public class Solution {

    public int xorOperation(int n, int start) {
        int s = start >> 1;
        int e = n & start & 1;

        int ret = sumXor(s - 1) ^ sumXor(s + n - 1);
s
        return ret << 1 | e;

    }

    public int sumXor(int x) {

        if (x % 4 == 0) {
            return x;
        } else if (x % 4 == 1){
            return 1;
        } else if (x % 4 == 2) {
            return x + 1;
        } else {
            return 0;
        }
    }
}
posted @   ShelterY  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示
主题色彩