leecode/problems/1310.xor-queries-of-a-subarray.md
2020-05-22 18:17:19 +08:00

169 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 题目地址1310. 子数组异或查询)
https://leetcode-cn.com/problems/xor-queries-of-a-subarray
## 题目描述
```
有一个正整数数组 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
```
## 暴力法
### 思路
最直观的思路是双层循环即可,果不其然超时了。
### 代码
```python
class Solution:
def xorQueries(self, arr: List[int], queries: List[List[int]]) -> List[int]:
res = []
for (L, R) in queries:
i = L
xor = 0
while i <= R:
xor ^= arr[i]
i += 1
res.append(xor)
return res
```
## 前缀表达式
### 思路
比较常见的是前缀和,这个概念其实很容易理解,即一个数组中,第 n 位存储的是数组前 n 个数字的和。
对 [1,2,3,4,5,6] 来说,其前缀和可以是 pre=[1,3,6,10,15,21]。我们可以使用公式 pre[𝑖]=pre[𝑖1]+nums[𝑖]得到每一位前缀和的值,从而通过前缀和进行相应的计算和解题。其实前缀和的概念很简单,但困难的是如何在题目中使用前缀和以及如何使用前缀和的关系来进行解题。
这道题是前缀对前缀异或,我们利用了异或的性质 `x ^ y ^ x = y`
![](https://tva1.sinaimg.cn/large/006tNbRwgy1gaqll5r048j30fm0bfglz.jpg)
### 代码
代码支持 Python3JavaC++
Python Code
```python
#
# @lc app=leetcode.cn id=1218 lang=python3
#
# [1218] 最长定差子序列
#
# @lc code=start
class Solution:
def xorQueries(self, arr: List[int], queries: List[List[int]]) -> List[int]:
pre = [0]
res = []
for i in range(len(arr)):
pre.append(pre[i] ^ arr[i])
for (L, R) in queries:
res.append(pre[L] ^ pre[R + 1])
return res
# @lc code=end
```
Java Code
```java
public int[] xorQueries(int[] arr, int[][] queries) {
int[] preXor = new int[arr.length];
preXor[0] = 0;
for (int i = 1; i < arr.length; i++)
preXor[i] = preXor[i - 1] ^ arr[i - 1];
int[] res = new int[queries.length];
for (int i = 0; i < queries.length; i++) {
int left = queries[i][0], right = queries[i][1];
res[i] = arr[right] ^ preXor[right] ^ preXor[left];
}
return res;
}
```
C++ Code:
```c++
class Solution {
public:
vector<int> xorQueries(vector<int>& arr, vector<vector<int>>& queries) {
vector<int>res;
for(int i=1; i<arr.size(); ++i){
arr[i]^=arr[i-1];
}
for(vector<int>temp :queries){
if(temp[0]==0){
res.push_back(arr[temp[1]]);
}
else{
res.push_back(arr[temp[0]-1]^arr[temp[1]]);
}
}
return res;
}
};
```
## 关键点解析
- 异或的性质 x ^ y ^ x = y
- 前缀表达式
## 相关题目
- [303. 区域和检索 - 数组不可变](https://leetcode-cn.com/problems/range-sum-query-immutable/description/)
![](https://tva1.sinaimg.cn/large/006tNbRwly1gaql7eqyg6j30u00ft0vx.jpg)
- [1186.删除一次得到子数组最大和](https://lucifer.ren/blog/2019/12/11/leetcode-1186/)