LeetCode-1310.[子数组异或查询]

0 阅读2分钟

1.题目描述

有一个正整数数组 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]

2.解题思路

利用异或的数学性质实现前缀异或

异或有三个核心性质(是优化的关键):

  • 交换律 / 结合律:a^b^c = a^(b^c) = (a^b)^c
  • 自反性:a^a = 0(相同数异或结果为 0);
  • 零元:a^0 = a(任何数和 0 异或结果不变)。

基于这些性质,我们构建前缀异或数组

  • 定义 prefix[0] = 0
  • prefix[i] = arr[0] ^ arr[1] ^ ... ^ arr[i-1]prefix[i] 表示前 i 个元素的异或和);
  • 对于查询 [l, r],区间异或结果 = prefix[l] ^ prefix[r+1](推导:prefix[r+1] = prefix[l] ^ (arr[l]^...^arr[r]),两边异或 prefix[l] 即可得到区间结果)。

3. 具体步骤

  1. 构建前缀异或数组 prefix
  2. 遍历每个查询,用 prefix[l] ^ prefix[r+1] 计算结果;
  3. 汇总所有查询结果并返回。

3.代码实现

class Solution {
public:
    vector<int> xorQueries(vector<int>& arr, vector<vector<int>>& queries) {
        // 1. 构建前缀异或数组(长度为arr.size()+1,prefix[0]=0)
        int n = arr.size();
        vector<int> prefix(n + 1, 0);
        for (int i = 1; i <= n; ++i) {
            prefix[i] = prefix[i - 1] ^ arr[i - 1];
        }

        // 2. 处理每个查询,计算区间异或结果
        vector<int> res;
        for (auto& q : queries) {
            int l = q[0];
            int r = q[1];
            // 核心公式:区间[l,r]的异或和 = prefix[l] ^ prefix[r+1]
            int xor_val = prefix[l] ^ prefix[r + 1];
            res.push_back(xor_val);
        } 

        return res;
    }
};