【Leetcode】1310. 子数组异或查询

253 阅读2分钟

子数组异或查询

有一个正整数数组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 // 返回运算结果
}