首页 > 其他分享 >leetcode 1486. 数组异或操作 https://leetcode.cn/problems/xor-operation-in-an-array/

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

时间:2024-08-07 17:09:19浏览次数:10  
标签:xor sumXor int 偶数 start 异或 4k array leetcode

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. \[{x⊕x = 0} \]

  2. \[{x⊕y = y⊕x} \]

  3. \[{(x⊕y)⊕z = x⊕(y⊕z)} \]

  4. \[{x⊕y⊕y = x} \]

  5. \[{∀i∈Z,有 4i⊕(4i+1)⊕(4i+2)⊕(4i+3)=0} \]

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

\[start⊕(start + 2)⊕(start + 4)⊕...⊕(start + 2(n - 1)) \]

观察原式,可以发现,每一个数列中的数奇偶性都是一样的,那么可以得知,数列中的每一个数的最低位或者都为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,即

\[最低位运算结果 = n⊕start⊕1 \]

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

\[\frac{1}{2}start⊕(\frac{1}{2}start + 1)⊕(\frac{1}{2}start + 2)⊕...⊕(\frac{1}{2}start + n - 1) \]

l令$${s = \frac{1}{2}start}$$,可得一个连续的数列

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

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

\[(s⊕(s + 1)⊕(s + 2)⊕...⊕(s + n - 1)) * 2 + e \]

这里需要注意:

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

对一串连续的整数数列,如$${}$$$${0⊕1⊕2⊕...⊕x}$$,根据第五条性质,可以得到

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

综上,可得表示$${0⊕1⊕2⊕...⊕x}$$的函数$${sumXor(x)}$$

\[sumXor(x) = \begin{cases} x, &x = 4k,k∈Z\\ (x−1)⊕x, &x = 4k + 1,k∈Z\\ (x−2)⊕(x−1)⊕x, &x = 4k + 2,k∈Z\\ (x−3)⊕(x−2)⊕(x−1)⊕x, &x = 4k + 3,k∈Z\\ \end{cases} \]

进一步化简,可得

\[sumXor(x) = \begin{cases} x, &x = 4k,k∈Z\\ 1, &x = 4k + 1,k∈Z\\ x+1, &x = 4k + 2,k∈Z\\ 0, &x = 4k + 3,k∈Z\\ \end{cases} \]

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

显然,$${x⊕y = sumXor(s + n - 1)}$$,所以$${x⊕y⊕y = sumXor(s + n - 1)⊕sumXor(s-1)}$$

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

\[(sumXor(s + n - 1)⊕sumXor(s-1)) * 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;
        }
    }
}

标签:xor,sumXor,int,偶数,start,异或,4k,array,leetcode
From: https://www.cnblogs.com/xly1029/p/18347412

相关文章

  • LeetCode150 逆波兰表达式求值
    前言题目:150.逆波兰表达式求值文档:代码随想录——逆波兰表达式求值编程语言:C++解题状态:成功解答!思路还是利用栈的思想,遍历到数字时,加入栈,遍历到运算符时,取出两个数进行运算,并将结果加入到栈中。代码classSolution{public:intevalRPN(vector<string>......
  • Leetcode 141. 环形链表(超详图解,解析过程)
    141.环形链表点击跳转leetcode原题给你一个链表的头节点head,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪next指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数pos来表示链表尾连接到链表中的位置(索引从0开始)。注意:pos......
  • C. Even Subarrays
    原题链接题解这题用到的知识点很多,思维+前缀异或+容斥原理。1、题目告诉我们要找被除数个数是偶数个的异或和,那么什么数的被除数有偶数个?答案:非完全平方数。2、非完全平方数太多了,不好求。而我们又知道所有序列个数为(n+1)*n/2所以我们只要求出序列异或和为完全平方数......
  • 每日一题:Leetcode-24 两两交换链表中的节点
    力扣题目解题思路java代码力扣题目:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。示例1:输入:head=[1,2,3,4]输出:[2,1,4,3]示例2:输入:head=[]输出:[]示例3:输入:head=[1]......
  • leetcode数论(1232. 缀点成线)-几何
    前言经过前期的基础训练以及部分实战练习,粗略掌握了各种题型的解题思路。现阶段开始专项练习。数论包含最大公约数(>=2个数)、最大公约数性质、最小公倍数、区间范围质因素计数(最下间隔)、质因素分解、判断质数、平方根、立方根、互质、同余等等。描述给定一个数组 coor......
  • 2024牛客暑期多校训练营7 C Array Sorting 题解
    乱搞非正解写法。分类讨论各种情况。降序排序对应交换即可数组个数小直接考虑相邻的交换其他都看做随机数据考虑结合前面情况,很容易想到,先把数组变成一个尽量有序的数组(每个元素和自己正确的位置相差不大)。最后再多次相邻交换,使得每个元素都在正确位置。把数组变成......
  • 《LeetCode热题100》---<5.②普通数组篇五道>
    本篇博客讲解LeetCode热题100道普通数组篇中的五道题第三道:轮转数组(中等)第四道:除自身以外数组的乘积(中等)第三道:轮转数组(中等) 方法一:使用额外的数组classSolution{publicvoidrotate(int[]nums,intk){intlen=nums.length;int[]newAr......
  • LeetCode-两数相加
    前言这道题将整数加法转换为在单链表上做加法运算,涉及到知识点:单链表的遍历单链表插入新节点题目描述给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。示例1:输入:l1=[2,4,3],l2=[5,6,4]输出:[7,0,8......
  • Number of k-good subarrays
    我们发现,如果我们将满足题意的点在数轴上标出,那么我们可以获得若干个连续段。对于一个长度为\(l\)的连续段,他对答案的贡献就是\(\frac{l(l+1)}{2}\),我们把所有连续段的贡献加起来就得到了答案于是我们发现这个可以拆分成子问题,具体见这篇题解。\(sol(n-mx,k-1)\)就是拆分成的子问......
  • LeetCode刷题-两数之和
    一、两数之和给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。示例1:输入:nums=......