medium XOR Queries of a Subarray
Problem Statement
You are given an array arr containing integers greater than 0. Additionally, you are given the array of queries where queries[i] = [lefti, righti].
For each query, compute the XOR of the elements in arr from index lefti to righti (inclusive)
Return an array answer where answer[i] represents the result of the ith query.
Examples
Example 1:
- Input: arr =
[2, 4, 7, 3], queries =[[0, 1], [1, 3], [0, 2]] - Expected Output:
[6, 0, 1] - Explanation:
- For the first query [0, 1], XOR of elements from index 0 to 1: 2 XOR 4 = 6
- For the second query [1, 3], XOR of elements from index 1 to 3: 4 XOR 7 XOR 3 = 0
- For the third query [0, 2], XOR of elements from index 0 to 2: 2 XOR 4 XOR 7 = 1
Example 2:
- Input: arr =
[5, 9, 12, 6], queries =[[2, 3], [0, 2], [1, 2]] - Expected Output:
[10, 0, 5] - Explanation:
- For the first query [2, 3], XOR of elements from index 2 to 3: 12 XOR 6 = 10
- For the second query [0, 2], XOR of elements from index 0 to 2: 5 XOR 9 XOR 12 = 0
- For the third query [1, 2], XOR of elements from index 1 to 2: 9 XOR 12 = 5
Example 3:
- Input: arr =
[1, 3, 5, 7, 9], queries =[[1, 4], [0, 3], [2, 4]] - Expected Output:
[8, 0, 11] - Explanation:
- For the first query [1, 4], XOR of elements from index 1 to 4: 3 XOR 5 XOR 7 XOR 9 = 8
- For the second query [0, 3], XOR of elements from index 0 to 3: 1 XOR 3 XOR 5 XOR 7 = 0
- For the third query [2, 4], XOR of elements from index 2 to 4: 5 XOR 7 XOR 9 = 11
Constraints:
- 1 <= arr.length, queries.length <= 3 * 104
- 1 <= arr[i] <= 109
- queries[i].length == 2
- 0 <= lefti <= righti < arr.length
Try it yourself
Try solving this question here:
✅ Solution XOR Queries of a Subarray
Problem Statement
You are given an array arr containing integers greater than 0. Additionally, you are given the array of queries where queries[i] = [lefti, righti].
For each query, compute the XOR of the elements in arr from index lefti to righti (inclusive)
Return an array answer where answer[i] represents the result of the ith query.
Examples
Example 1:
- Input: arr =
[2, 4, 7, 3], queries =[[0, 1], [1, 3], [0, 2]] - Expected Output:
[6, 0, 1] - Explanation:
- For the first query [0, 1], XOR of elements from index 0 to 1: 2 XOR 4 = 6
- For the second query [1, 3], XOR of elements from index 1 to 3: 4 XOR 7 XOR 3 = 0
- For the third query [0, 2], XOR of elements from index 0 to 2: 2 XOR 4 XOR 7 = 1
Example 2:
- Input: arr =
[5, 9, 12, 6], queries =[[2, 3], [0, 2], [1, 2]] - Expected Output:
[10, 0, 5] - Explanation:
- For the first query [2, 3], XOR of elements from index 2 to 3: 12 XOR 6 = 10
- For the second query [0, 2], XOR of elements from index 0 to 2: 5 XOR 9 XOR 12 = 0
- For the third query [1, 2], XOR of elements from index 1 to 2: 9 XOR 12 = 5
Example 3:
- Input: arr =
[1, 3, 5, 7, 9], queries =[[1, 4], [0, 3], [2, 4]] - Expected Output:
[8, 0, 11] - Explanation:
- For the first query [1, 4], XOR of elements from index 1 to 4: 3 XOR 5 XOR 7 XOR 9 = 8
- For the second query [0, 3], XOR of elements from index 0 to 3: 1 XOR 3 XOR 5 XOR 7 = 0
- For the third query [2, 4], XOR of elements from index 2 to 4: 5 XOR 7 XOR 9 = 11
Constraints:
- 1 <= arr.length, queries.length <= 3 * 104
- 1 <= arr[i] <= 109
- queries[i].length == 2
- 0 <= lefti <= righti < arr.length
Solution
To solve this problem, we can use Mo's Algorithm, which is a powerful technique used to answer multiple queries on an array in an efficient manner. The core idea is to sort the queries in a way that minimizes the amount of work needed to process them. We can do this by sorting based on the blocks of the query ranges and then processing each block while keeping track of the current XOR value. By moving the pointers to include or exclude elements in the current range, we can quickly compute the XOR for each query without recalculating from scratch.
This approach is effective because it reduces the time complexity compared to a naive approach where we would recompute the XOR for every query from scratch. By reusing the results from previous computations, we can answer each query in sub-linear time relative to the size of the array, making the algorithm scalable even for large inputs.
Step-by-Step Algorithm
-
Initialization:
- Define a class
Querythat stores each query'sleft,rightindices and its original index in thequeriesarray. This is essential for keeping track of the order of queries after sorting. - Initialize
blockSizeas the square root of the length ofarr. - Create an array
qs[]to store the queries asQueryobjects, with each query’sleft,right, and original index.
- Define a class
-
Sort Queries:
- Sort the queries in
qs[]based on:- Block index calculated by
left / blockSize. - If two queries have the same block index, sort by
rightindex.
- Block index calculated by
- This ordering minimizes the movement of
currentLeftandcurrentRightpointers during query processing.
- Sort the queries in
-
Initialize Pointers:
- Set
currentLeftto 0,currentRightto -1, andcurrentXorto 0. - These pointers track the current segment of
arr[]being processed, andcurrentXorstores the XOR of this segment.
- Set
-
Process Each Query:
- For each query in the sorted
qs[]:- Expand
currentRight: WhilecurrentRightis less thanquery.right, movecurrentRightto the right, including new elements in the XOR calculation. - Shrink
currentRight: WhilecurrentRightis greater thanquery.right, movecurrentRightto the left, excluding elements from the XOR calculation. - Expand
currentLeft: WhilecurrentLeftis less thanquery.left, movecurrentLeftto the right, excluding elements from the XOR calculation. - Shrink
currentLeft: WhilecurrentLeftis greater thanquery.left, movecurrentLeftto the left, including new elements in the XOR calculation.
- Expand
- After adjusting
currentLeftandcurrentRight, store the computedcurrentXorinanswer[query.index].
- For each query in the sorted
-
Return the Results:
- Once all queries are processed, return the
answer[]array containing the results for each query.
- Once all queries are processed, return the
Algorithm Walkthrough
Let’s walk through the algorithm with arr = [2, 4, 7, 3] and queries = [[0, 1], [1, 3], [0, 2]].
Step 1: Initialization
queries = [[0, 1], [1, 3], [0, 2]]blockSize = 2(sincesqrt(4) = 2)answer[] = [0, 0, 0]
Step 2: Create Query objects
qs[0] = Query(0, 1, 0)→ corresponds to the first query.qs[1] = Query(1, 3, 1)→ corresponds to the second query.qs[2] = Query(0, 2, 2)→ corresponds to the third query.
Step 3: Sort the queries (qs[] array)
- Here,
blockSize = 2. All queries belong to the first block. The sorted Queries are:qs[0] = Query(0, 1, 0)qs[1] = Query(0, 2, 2)qs[2] = Query(1, 3, 1)
Step 4: Initialize pointers and currentXor
currentLeft = 0currentRight = -1currentXor = 0
Step 5: Process the first query (Query(0, 1, 0))
- Expand
currentRightto 1:currentRight = 0,currentXor = 0 XOR arr[0] = 0 XOR 2 = 2currentRight = 1,currentXor = 2 XOR arr[1] = 2 XOR 4 = 6
- No need to move
currentLeftas it's already 0. - Store result:
answer[0] = 6
Step 6: Process the second query (Query(0, 2, 2))
- Expand
currentRightto 2:currentRight = 2,currentXor = 6 XOR arr[2] = 6 XOR 7 = 1
- No need to move
currentLeftas it's already 0. - Store result:
answer[2] = 1
Step 7: Process the third query (Query(1, 3, 1))
- Expand
currentRightto 3:currentRight = 3,currentXor = 1 XOR arr[3] = 1 XOR 3 = 2
- Move
currentLeftto 1:currentXor = 2 XOR arr[0] = 2 XOR 2 = 0
- Store result:
answer[1] = 0
Final Output:
answer[] = [6, 0, 1]
Code
import java.util.Arrays;
class Query {
int left, right, index;
Query(int l, int r, int i) {
left = l;
right = r;
index = i;
}
}
class Solution {
public int[] xorQueries(int[] arr, int[][] queries) {
int n = arr.length;
int q = queries.length;
int blockSize = (int) Math.sqrt(n); // Size of each block for Mo's algorithm
int[] answer = new int[q];
// Create an array of Query objects to hold the queries with their indices
Query[] qs = new Query[q];
for (int i = 0; i < q; i++) {
qs[i] = new Query(queries[i][0], queries[i][1], i);
}
// Sort the queries according to the block and then by the right index
Arrays.sort(qs, (a, b) -> {
int blockA = a.left / blockSize;
int blockB = b.left / blockSize;
if (blockA != blockB) return blockA - blockB; // Sort by block
return a.right - b.right; // Sort by right index if in the same block
});
int currentLeft = 0,
currentRight = -1,
currentXor = 0; // Initialize pointers and current XOR
// Process each query in the sorted order
for (Query query : qs) {
// Expand the right boundary to include new elements in the XOR calculation
while (currentRight < query.right) {
currentRight++;
currentXor ^= arr[currentRight];
}
// Shrink the right boundary to exclude elements from the XOR calculation
while (currentRight > query.right) {
currentXor ^= arr[currentRight];
currentRight--;
}
// Expand the left boundary to exclude elements from the XOR calculation
while (currentLeft < query.left) {
currentXor ^= arr[currentLeft];
currentLeft++;
}
// Shrink the left boundary to include new elements in the XOR calculation
while (currentLeft > query.left) {
currentLeft--;
currentXor ^= arr[currentLeft];
}
answer[query.index] = currentXor;
}
return answer;
}
// Main method to test the xorQueries method with provided examples
public static void main(String[] args) {
Solution solution = new Solution();
// Example 1
int[] arr1 = { 2, 4, 7, 3 };
int[][] queries1 = { { 0, 1 }, { 1, 3 }, { 0, 2 } };
int[] result1 = solution.xorQueries(arr1, queries1);
System.out.println("Example 1 Output: " + Arrays.toString(result1)); // Expected Output: [6, 0, 1]
// Example 2
int[] arr2 = { 5, 9, 12, 6 };
int[][] queries2 = { { 2, 3 }, { 0, 2 }, { 1, 2 } };
int[] result2 = solution.xorQueries(arr2, queries2);
System.out.println("Example 2 Output: " + Arrays.toString(result2)); // Expected Output: [10, 0, 5]
// Example 3
int[] arr3 = { 1, 3, 5, 7, 9 };
int[][] queries3 = { { 1, 4 }, { 0, 3 }, { 2, 4 } };
int[] result3 = solution.xorQueries(arr3, queries3);
System.out.println("Example 3 Output: " + Arrays.toString(result3)); // Expected Output: [8, 0, 11]
}
}
Complexity Analysis
Time Complexity
The overall time complexity is
Space Complexity
- Space for Results: Storing the results for each query takes
space. - Auxiliary Space: The array and auxiliary data structures require
space.
Overall Space Complexity:
🤖 Don't fully get this? Learn it with Claude
Stuck on XOR Queries of a Subarray? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **XOR Queries of a Subarray** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **XOR Queries of a Subarray** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **XOR Queries of a Subarray**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **XOR Queries of a Subarray**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.