子数组异或查询
有一个正整数数组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]
思路
- 看到这个题目,首先想到的是暴力求解,外层循环就是遍历queries,内层循环就是根据queries[i]=[Li,Ri],遍历arr。如解法一。
- 异或值求解,首先想到的是常见的解决法则“前缀异或值”。
dp[i]=arr[0]^arr[1]^...^arr[i-1]
arr[left]^arr[left+1]^arr[left+2]^...^arr[right]
=arr[0]^arr[1]^...^arr[left-1]^arr[0]^arr[1]^...^arr[left-1]^arr[left]^arr[left+1]^...^arr[right]
=dp[left]^dp[right+1]
- 在本题中,主要使用了异或运算的结合律和a^a=0,0^b=b
解法一
func xorQueries(arr []int, queries [][]int) []int {
res:=[]int{}
for i:=0;i<len(queries);i++{ // 外层循环遍历数组
left:=queries[i][0] // 获取元素的左索引
right:=queries[i][1] // 获取元素的右索引
temp:=arr[left]
for j:=left+1;j<=right;j++{ // 内层循环获取在上述左右索引范围内的异或值
temp=temp^arr[j]
}
res=append(res,temp)
}
return res // 返回运算结果
}
解法二
func xorQueries(arr []int, queries [][]int) []int {
res:=[]int{} // 定义存放结果的数组
dp:=make([]int,len(arr)+1)
for i:=0;i<len(arr);i++{ // 计算前缀异或数组
dp[i+1]=dp[i]^arr[i]
}
for _,v:=range queries{ // 计算查询的结果,每个结果都使用到上述的规律dp[left]^dp[right+1]
temp:=dp[v[0]]^dp[v[1]+1]
res=append(res,temp)
}
return res // 返回运算结果
}