欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > 前缀和题目:子数组异或查询

前缀和题目:子数组异或查询

2025/6/13 9:41:56 来源:https://blog.csdn.net/stormsunshine/article/details/126068770  浏览:    关键词:前缀和题目:子数组异或查询

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:子数组异或查询

出处:1310. 子数组异或查询

难度

4 级

题目描述

要求

给定一个正整数数组 arr \texttt{arr} arr,以及一个查询数组 queries \texttt{queries} queries,其中 queries[i] = [left i , right i ] \texttt{queries[i] = [left}_\texttt{i}\texttt{, right}_\texttt{i}\texttt{]} queries[i] = [lefti, righti]

对于每个查询 i \texttt{i} i,计算从 left i \texttt{left}_\texttt{i} lefti right i \texttt{right}_\texttt{i} righti 的异或值(即 arr[left i ] ⊕ arr[left i + 1] ⊕ … ⊕ arr[right i ] \texttt{arr[left}_\texttt{i}\texttt{]} \oplus \texttt{arr[left}_\texttt{i}\texttt{ + 1]} \oplus \ldots \oplus \texttt{arr[right}_\texttt{i}\texttt{]} arr[lefti]arr[lefti + 1]arr[righti])作为查询的结果。

返回一个数组 answer \texttt{answer} answer,其中 answer[i] \texttt{answer[i]} answer[i] 是第 i \texttt{i} i 个查询的结果。

示例

示例 1:

输入: arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]] \texttt{arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]]} arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]]
输出: [2,7,14,8] \texttt{[2,7,14,8]} [2,7,14,8]
解释:
数组中元素的二进制表示形式是:
1 = 0001 \texttt{1} = \texttt{0001} 1=0001
3 = 0011 \texttt{3} = \texttt{0011} 3=0011
4 = 0100 \texttt{4} = \texttt{0100} 4=0100
8 = 1000 \texttt{8} = \texttt{1000} 8=1000
查询的异或值为:
[0,1] = 1 ⊕ 3 = 2 \texttt{[0,1]} = \texttt{1} \oplus \texttt{3} = \texttt{2} [0,1]=13=2
[1,2] = 3 ⊕ 4 = 7 \texttt{[1,2]} = \texttt{3} \oplus \texttt{4} = \texttt{7} [1,2]=34=7
[0,3] = 1 ⊕ 3 ⊕ 4 ⊕ 8 = 14 \texttt{[0,3]} = \texttt{1} \oplus \texttt{3} \oplus \texttt{4} \oplus \texttt{8} = \texttt{14} [0,3]=1348=14
[3,3] = 8 \texttt{[3,3]} = \texttt{8} [3,3]=8

示例 2:

输入: arr = [4,8,2,10], queries = [[2,3],[1,3],[0,0],[0,3]] \texttt{arr = [4,8,2,10], queries = [[2,3],[1,3],[0,0],[0,3]]} arr = [4,8,2,10], queries = [[2,3],[1,3],[0,0],[0,3]]
输出: [8,0,4,4] \texttt{[8,0,4,4]} [8,0,4,4]

数据范围

  • 1 ≤ arr.length ≤ 3 × 10 4 \texttt{1} \le \texttt{arr.length} \le \texttt{3} \times \texttt{10}^\texttt{4} 1arr.length3×104
  • 1 ≤ arr[i] ≤ 10 9 \texttt{1} \le \texttt{arr[i]} \le \texttt{10}^\texttt{9} 1arr[i]109
  • 1 ≤ queries.length ≤ 3 × 10 4 \texttt{1} \le \texttt{queries.length} \le \texttt{3} \times \texttt{10}^\texttt{4} 1queries.length3×104
  • queries[i].length = 2 \texttt{queries[i].length} = \texttt{2} queries[i].length=2
  • 0 ≤ left i ≤ right i < arr.length \texttt{0} \le \texttt{left}_\texttt{i} \le \texttt{right}_\texttt{i} < \texttt{arr.length} 0leftirighti<arr.length

解法

思路和算法

这道题要求对于每个查询计算子数组的元素按位异或。由于数组 arr \textit{arr} arr 的长度以及查询的个数最大为 3 × 10 4 3 \times 10^4 3×104,因此计算子数组的元素按位异或时,不能使用遍历子数组的做法,而是需要使用时间复杂度更低的做法。可以使用前缀和的思想实现。

首先计算数组 arr \textit{arr} arr 的前缀异或数组。创建前缀异或数组 prefixXors \textit{prefixXors} prefixXors,其长度为 arr \textit{arr} arr 的长度加 1 1 1 prefixXors [ i ] \textit{prefixXors}[i] prefixXors[i] 表示 arr \textit{arr} arr 的长度为 i i i 的前缀异或,即下标范围 [ 0 , i − 1 ] [0, i - 1] [0,i1] 中的 i i i 个元素的按位异或。

根据按位异或的性质, prefixXors [ i + 1 ] ⊕ prefixXors [ i ] = arr [ i ] \textit{prefixXors}[i + 1] \oplus \textit{prefixXors}[i] = \textit{arr}[i] prefixXors[i+1]prefixXors[i]=arr[i] prefixXors [ i + 1 ] = prefixXors [ i ] ⊕ arr [ i ] \textit{prefixXors}[i + 1] = \textit{prefixXors}[i] \oplus \textit{arr}[i] prefixXors[i+1]=prefixXors[i]arr[i],由此可以遍历数组 arr \textit{arr} arr 一次计算得到前缀异或数组。

得到前缀异或数组 prefixXors \textit{prefixXors} prefixXors 之后,对于 queries [ i ] = [ left i , right i ] \textit{queries}[i] = [\textit{left}_i, \textit{right}_i] queries[i]=[lefti,righti],查询结果可以通过前缀异或数组得到:

answer [ i ] = prefixXors [ right i + 1 ] ⊕ prefixXors [ left i ] \textit{answer}[i] = \textit{prefixXors}[\textit{right}_i + 1] \oplus \textit{prefixXors}[\textit{left}_i] answer[i]=prefixXors[righti+1]prefixXors[lefti]

代码

class Solution {public int[] xorQueries(int[] arr, int[][] queries) {int length = arr.length;int[] prefixXors = new int[length + 1];for (int i = 0; i < length; i++) {prefixXors[i + 1] = prefixXors[i] ^ arr[i];}int queriesCount = queries.length;int[] answer = new int[queriesCount];for (int i = 0; i < queriesCount; i++) {int left = queries[i][0], right = queries[i][1];answer[i] = prefixXors[right + 1] ^ prefixXors[left];}return answer;}
}

复杂度分析

  • 时间复杂度: O ( n + q ) O(n + q) O(n+q),其中 n n n 是数组 arr \textit{arr} arr 的长度, q q q 是数组 queries \textit{queries} queries 的长度。需要遍历数组 arr \textit{arr} arr 一次计算前缀异或数组,需要遍历数组 queries \textit{queries} queries 一次计算每个查询的结果,每个查询的计算时间是 O ( 1 ) O(1) O(1),因此时间复杂度是 O ( n + q ) O(n + q) O(n+q)

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 arr \textit{arr} arr 的长度。需要创建长度为 n + 1 n + 1 n+1 的前缀异或数组。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词