有一个正整数数组 arr
,现给你一个对应的查询数组 queries
,其中 queries[i] = [Li, Ri]
。
对于每个查询 i
,请你计算从 Li
到 Ri
的 XOR 值(即 arr[Li] xor arr[Li+1] xor ... xor arr[Ri]
)作为本次查询的结果。
并返回一个包含给定查询 queries
所有结果的数组。
示例 1:
输入:arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]] 输出:[2,7,14,8] 解释: 数组中元素的二进制表示形式是: 1 = 0001 3 = 0011 4 = 0100 8 = 1000 查询的 XOR 值为: [0,1] = 1 xor 3 = 2 [1,2] = 3 xor 4 = 7 [0,3] = 1 xor 3 xor 4 xor 8 = 14 [3,3] = 8
示例 2:
输入:arr = [4,8,2,10], queries = [[2,3],[1,3],[0,0],[0,3]] 输出:[8,0,4,4]
提示:
1 <= arr.length <= 3 * 10^4
1 <= arr[i] <= 10^9
1 <= queries.length <= 3 * 10^4
queries[i].length == 2
0 <= queries[i][0] <= queries[i][1] < arr.length
提示 1
What is the result of x ^ y ^ x ?
提示 2
Compute the prefix sum for XOR.
解法1: 前缀异或
定义长度为 n+1 的前缀异或数组 prexor。令 prexor[0]=0,对于 0≤i<n,prexor[i+1]=prexor[i]⊕arr[i],其中 ⊕ 是异或运算符。当 1≤i≤n 时,prexor[i] 为从 arr[0] 到 arr[i−1] 的元素的异或运算结果:
prexor[i]=arr[0]⊕…⊕arr[i−1]
对于查询 [left,right](left≤right),用 Q(left,right) 表示该查询的结果。
- 当 left=0 时,Q(left,right)=prexor[right+1]。
- 当 left>0 时,Q(left,right) 的计算如下:
Q(left,right)
=arr[left]⊕…⊕arr[right]
=(arr[0]⊕…⊕arr[left−1])⊕(arr[0]⊕…⊕arr[left−1])⊕(arr[left]⊕…⊕arr[right])
=(arr[0]⊕…⊕arr[left−1])⊕(arr[0]⊕…⊕arr[right])
=prexor[left]⊕prexor[right+1]
上述计算用到了异或运算的结合律,以及异或运算的性质 x⊕x=0。
当 left=0 时,prexor[left]=0,因此 Q(left,right)=prexor[left]⊕prexor[right+1] 也成立。
因此对任意 0≤left≤right<n,都有 Q(left,right)=prexor[left]⊕prexor[right+1],即可在 O(1) 的时间内完成一个查询的计算。
根据上述分析,这道题可以分两步求解。
计算前缀异或数组 prexor;
计算每个查询的结果,第 i 个查询的结果为 prexor[queries[i][0]]⊕prexor[queries[i][1]+1]。
Java版:
class Solution {
public int[] xorQueries(int[] arr, int[][] queries) {
int n = arr.length;
int[] prexor = new int[n + 1];
for (int i = 0; i < n; i++) {
prexor[i + 1] = prexor[i] ^ arr[i];
}
int m = queries.length;
int[] ans = new int[m];
for (int i = 0; i < m; i++) {
ans[i] = (prexor[queries[i][1] + 1]) ^ prexor[queries[i][0]];
}
return ans;
}
}
Python3版:
class Solution:
def xorQueries(self, arr: List[int], queries: List[List[int]]) -> List[int]:
n = len(arr)
prexor = [0] * (n + 1)
for i in range(n):
prexor[i + 1] = prexor[i] ^ arr[i]
m = len(queries)
ans = [0] * m
for i in range(m):
ans[i] = prexor[queries[i][1] + 1] ^ prexor[queries[i][0]]
return ans
复杂度分析
- 时间复杂度:O(n+m),其中 n 是数组 arr 的长度,m 是数组 queries 的长度。需要遍历数组 arr 一次,计算前缀异或数组的每个元素值,然后对每个查询分别使用 O(1) 的时间计算查询结果。
- 空间复杂度:O(n+m),其中 n 是数组 arr 的长度,m 是数组 queries 的长度。