Given two integers L and R. Find the XOR of the elements in the range [L , R].
Input : L = 3 , R = 5
Output : 2
Explanation : answer = (3 ^ 4 ^ 5) = 2.
Input : L = 1, R = 3
Output : 0
Explanation : answer = (1 ^ 2 ^ 3) = 2.
Input : L = 4, R = 10
A naive approach to solving this will be XOR for every number in the given range.
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/* Function to find the XOR
of numbers from L to R*/
int findRangeXOR(int l, int r){
// To store the XOR of numbers
int ans = 0;
// XOR all the numbers
for(int i=l; i <= r; i++) {
ans ^= i;
}
// Return the result
return ans;
}
};
int main() {
int l = 3, r = 5;
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to get the
XOR of numbers from L to R*/
int ans = sol.findRangeXOR(l, r);
cout << "The XOR of numbers from " << l << " to " << r << " is: " << ans;
return 0;
}
class Solution {
/* Function to find the XOR
of numbers from L to R */
public int findRangeXOR(int l, int r) {
// To store the XOR of numbers
int ans = 0;
// XOR all the numbers
for (int i = l; i <= r; i++) {
ans ^= i;
}
// Return the result
return ans;
}
public static void main(String[] args) {
int l = 3, r = 5;
/* Creating an instance of
Solution class */
Solution sol = new Solution();
/* Function call to get the
XOR of numbers from L to R */
int ans = sol.findRangeXOR(l, r);
System.out.println("The XOR of numbers from " + l + " to " + r + " is: " + ans);
}
}
class Solution:
# Function to find the XOR
# of numbers from L to R
def findRangeXOR(self, l, r):
# To store the XOR of numbers
ans = 0
# XOR all the numbers
for i in range(l, r + 1):
ans ^= i
# Return the result
return ans
if __name__ == "__main__":
l, r = 3, 5
# Creating an instance of
# Solution class
sol = Solution()
# Function call to get the
# XOR of numbers from L to R
ans = sol.findRangeXOR(l, r)
print(f"The XOR of numbers from {l} to {r} is: {ans}")
class Solution {
/* Function to find the XOR
of numbers from L to R */
findRangeXOR(l, r) {
// To store the XOR of numbers
let ans = 0;
// XOR all the numbers
for (let i = l; i <= r; i++) {
ans ^= i;
}
// Return the result
return ans;
}
}
const main = () => {
const l = 3, r = 5;
/* Creating an instance of
Solution class */
const sol = new Solution();
/* Function call to get the
XOR of numbers from L to R */
const ans = sol.findRangeXOR(l, r);
console.log(`The XOR of numbers from ${l} to ${r} is: ${ans}`);
};
main();
Time Complexity: O(N) Traversing through all the numbers take O(N) time.
Space Complexity: O(1) Using only a couple of variables, i.e., constant space.
XORing every number in the given range will be time-consuming and not very efficient.
To solve this problem efficiently, the following observation will come in hand:
The XOR of numbers from 1 to n follows a pattern based on the value of n % 4
.
n % 4 = 0
, XOR from 1 to n is n.n % 4 = 1
, XOR from 1 to n is 1.n % 4 = 2
, XOR from 1 to n is n+1.n % 4 = 3
, XOR from 1 to n is 0.n % 4
and return the result based on the identified pattern using a separate function.#include <bits/stdc++.h>
using namespace std;
class Solution {
private:
/* Function to find the XOR
of numbers from 1 to n*/
int XORtillN(int n) {
if(n % 4 == 1) return 1;
if(n % 4 == 2) return n+1;
if(n % 4 == 3) return 0;
return n;
}
public:
/* Function to find the XOR
of numbers from L to R*/
int findRangeXOR(int l, int r){
return XORtillN(l-1) ^ XORtillN(r);
}
};
int main() {
int l = 3, r = 5;
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to get the
XOR of numbers from L to R*/
int ans = sol.findRangeXOR(l, r);
cout << "The XOR of numbers from " << l << " to " << r << " is: " << ans;
return 0;
}
import java.util.*;
class Solution {
/* Function to find the XOR
of numbers from 1 to n */
private int XORtillN(int n) {
if(n % 4 == 1) return 1;
if(n % 4 == 2) return n + 1;
if(n % 4 == 3) return 0;
return n;
}
/* Function to find the XOR
of numbers from L to R */
public int findRangeXOR(int l, int r) {
return XORtillN(l - 1) ^ XORtillN(r);
}
public static void main(String[] args) {
int l = 3, r = 5;
/* Creating an instance of
Solution class */
Solution sol = new Solution();
/* Function call to get the
XOR of numbers from L to R */
int ans = sol.findRangeXOR(l, r);
System.out.println("The XOR of numbers from " + l + " to " + r + " is: " + ans);
}
}
class Solution:
# Function to find the XOR
# of numbers from 1 to n
def XORtillN(self, n):
if n % 4 == 1:
return 1
if n % 4 == 2:
return n + 1
if n % 4 == 3:
return 0
return n
# Function to find the XOR
# of numbers from L to R
def findRangeXOR(self, l, r):
return self.XORtillN(l - 1) ^ self.XORtillN(r)
if __name__ == "__main__":
l, r = 3, 5
# Creating an instance of
# Solution class
sol = Solution()
# Function call to get the
# XOR of numbers from L to R
ans = sol.findRangeXOR(l, r)
print(f"The XOR of numbers from {l} to {r} is: {ans}")
class Solution {
/* Function to find the XOR
of numbers from 1 to n */
XORtillN(n) {
if (n % 4 === 1) return 1;
if (n % 4 === 2) return n + 1;
if (n % 4 === 3) return 0;
return n;
}
/* Function to find the XOR
of numbers from L to R */
findRangeXOR(l, r) {
return this.XORtillN(l - 1) ^ this.XORtillN(r);
}
}
const l = 3, r = 5;
/* Creating an instance of
Solution class */
const sol = new Solution();
/* Function call to get the
XOR of numbers from L to R */
const ans = sol.findRangeXOR(l, r);
console.log(`The XOR of numbers from ${l} to ${r} is: ${ans}`);
Time Complexity: O(1) Using constant time operations.
Space Complexity: O(1) Using a couple of variables i.e., constant space.
Q: How does the modulo 4 pattern arise?
A: The XOR pattern for numbers from 0 to N repeats every 4 numbers because of the binary properties of XOR and the carry propagation in binary addition.
Q: Why does XOR work for ranges?
A: XOR has the property that a⊕a=0 and a⊕0=a. This allows numbers outside the range L to R to cancel out when computing XOR(0 to R)⊕XOR(0 to L−1).
Q: How would you extend this to compute XOR for multiple ranges?
A: For multiple ranges, precompute the cumulative XOR for all numbers up to the maximum R across all ranges. Then, use the same logic (f(R)⊕f(L-1)) for each range in O(1) time.