题目:1310. 子数组异或查询
难度: 中等
题目:
有一个正整数数组 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xor-queries-of-a-subarray/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
首先,我们需要了解异或的性质:
-
异或运算满足交换律和结合律;
-
任意整数和自身做异或运算的结果都等于0,即x⊕x=0;
-
任意整数和0做异或运算的结果都等于其自身,即x⊕0=0⊕x=x。
本题的时间复杂度为O(mn),要想降低维度,需要将查询从O(n)到O(1)。因此,可以采取前缀和的方式,降低复杂度。
解题代码
class Solution {
public:
vector<int> xorQueries(vector<int>& arr, vector<vector<int>>& queries) {
int n = arr.size();
vector<int> xors(n + 1);
xors[0] = 0;//前缀和数组,每个元素等于前一个异或,叠加异或
for (int i = 1; i < n + 1; i++)
{
xors[i] = xors[i - 1] ^ arr[i - 1];
}
//xors[i]表示前i个相互异或的结果
//对于,q[left][right]
/*
1.left=0,那么q[left][right] = q[0][right] = xors[right - 1]
2.left!=0,那么:
q[left][right] = q[left]^q[left+1]^.....^q[right]
异或自身=0 = q[0]...q[left-1] ^ q[0]...q[left-1] ^ q[left].....q[right]
= q[0]...q[left-1] ^ xors[right+1]
= xors[left] ^ xors[right+1]
而,xors[0]=0,0异或本身还是原来的,所以两种情况合并:q[left][right] = xors[left] ^ xors[right+1]
*/
int m = queries.size();
vector<int> ans;
for (int i = 0; i < m; i++)
{
int left = queries[i][0];
int right = queries[i][1];
ans.push_back(xors[left] ^ xors[right + 1]);
}
return ans;
}
};