LeetCode 1310. 子数组异或查询

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

提示 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 的长度。
  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值