LeetCode1486. 数组异或操作
Posted Zephyr丶J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode1486. 数组异或操作相关的知识,希望对你有一定的参考价值。
LeetCode1486. 数组异或操作
题目描述
给你两个整数,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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xor-operation-in-an-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
又是一道异或题,看了半天异或的性质没发现有啥规律,所以直接写了,没想到还过了
class Solution {
public int xorOperation(int n, int start) {
//挨个去异或吗,感觉不靠谱啊,先写一下吧,推了半天规律推不出来
int res = start;
for(int i = 1; i < n; i++){
res ^= 2 * i + start;
}
return res;
}
}
然后就去看解答,然后看的我也是一知半解的。写一下自己理解到的:
求这个式子的值 (start) ^ (start+2) ^ (start+4) ^ (start+6) ^ … ^ (start+2(n-1))
首先,因为每两个数相差2,因此如果是start是偶数的话,所有数的末位都是0,异或还是0
如果start是奇数的话,所有项的末位都是1,当n为偶数的时候,异或是0;n为奇数的时候,异或是1
然后将这个式子除以2,得到 (s) ^ (s+1) ^ (s+2) ^ (s+3) ^ … ^ (s+(n-1)) * 2 + b
其中s就等于start/2,其中b就是单独的那个末位,这个末位上面已经提过怎么求了,那么接下来就是
(s) ^ (s+1) ^ (s+2) ^ (s+3) ^ … ^ (s+(n-1)) 的求法(它的二倍就是向右移一位)
因为相同的数异或结果为0,因此上面的式子可以写成
(s) ^ (s+1) ^ (s+2) ^ (s+3) ^ … ^ (s+(n-1)) = (1 ^ 2 ^ … ^ s - 1)^(1 ^ 2 ^ … ^ s + n - 1)
(根据异或的交换律和结合律可以将前面的s-1项相异或,为0,因此可以这样转换)
这样,就变成了如何求 1 到 n 的异或
然后观察每四个数的规律,即4k,4k+1,4k+2,4k+3,可以发现4k ^ 4k + 1 = 1(只有末尾的1不同)
4k ^ 4k + 1 ^ 4k + 2 = 4k + 3(1与4k+2异或,只把末尾的0变成了1)
4k ^ 4k + 1 ^ 4k + 2 ^ 4k + 3 = 4k + 3 ^ 4k + 3 = 0
这样,得到了最后的运算规律,就可以将原来O(n)的复杂度降低到O(1)
(说实话,不好想,有点难,感觉意义不大,记住最后每四个数的规律就行了)
class Solution {
public int xorOperation(int n, int start) {
//按规律
int s = start / 2;
int b = start & n & 1; //最后一位二进制位,全1为1,有0就为0,是与的关系
int res = xor(s - 1) ^ xor(s + n - 1);
return res << 1 | b;
}
public int xor(int n){
if(n % 4 == 0)
return n;
if(n % 4 == 1)
return 1;
if(n % 4 == 2)
return n + 1;
return 0;
}
}
以上是关于LeetCode1486. 数组异或操作的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode1486. 数组异或操作(Java/c++ 暴力模拟)