🧠
Optimal XOR Partitioning
💡 This approach uses XOR properties to find the two missing numbers without arithmetic overflow or complex algebra. It is elegant and efficient.
Intuition
XOR all numbers from 1 to n and XOR all elements in the array. The result is XOR of the two missing numbers. Use a set bit to partition numbers into two groups and XOR separately to find the missing numbers.
Algorithm
- XOR all numbers from 1 to n and XOR all elements in the array to get xor_missing = x ^ y.
- Find a set bit in xor_missing to partition numbers into two groups.
- XOR numbers in each group separately for both the full range and the array.
- The two results are the missing numbers.
💡 This algorithm cleverly uses XOR to separate the two missing numbers without extra space or arithmetic.
def find_two_missing_xor(n, arr):
xor_all = 0
for i in range(1, n+1):
xor_all ^= i
for num in arr:
xor_all ^= num
# Find rightmost set bit
set_bit = xor_all & (-xor_all)
x = 0
y = 0
for i in range(1, n+1):
if i & set_bit:
x ^= i
else:
y ^= i
for num in arr:
if num & set_bit:
x ^= num
else:
y ^= num
return [x, y]
# Driver code
if __name__ == '__main__':
n = 6
arr = [1, 2, 4, 6]
print(find_two_missing_xor(n, arr))
Line Notes
xor_all = 0Initialize XOR accumulator
xor_all ^= iXOR all numbers from 1 to n
for num in arr: xor_all ^= numXOR all elements in the array to cancel out present numbers
set_bit = xor_all & (-xor_all)Find rightmost set bit to partition numbers
x = 0; y = 0Initialize variables to hold the two missing numbers
for i in range(1, n+1): if i & set_bit: x ^= i else: y ^= iPartition numbers based on set bit and XOR separately
for num in arr: if num & set_bit: x ^= num else: y ^= numPartition array elements similarly to cancel out present numbers
return [x, y]Return the two missing numbers
import java.util.*;
public class FindTwoMissing {
public static int[] findTwoMissingXOR(int n, int[] arr) {
int xorAll = 0;
for (int i = 1; i <= n; i++) xorAll ^= i;
for (int num : arr) xorAll ^= num;
int setBit = xorAll & (-xorAll);
int x = 0, y = 0;
for (int i = 1; i <= n; i++) {
if ((i & setBit) != 0) x ^= i;
else y ^= i;
}
for (int num : arr) {
if ((num & setBit) != 0) x ^= num;
else y ^= num;
}
return new int[]{x, y};
}
public static void main(String[] args) {
int n = 6;
int[] arr = {1, 2, 4, 6};
System.out.println(Arrays.toString(findTwoMissingXOR(n, arr)));
}
}
Line Notes
int xorAll = 0Initialize XOR accumulator
for (int i = 1; i <= n; i++) xorAll ^= iXOR all numbers from 1 to n
for (int num : arr) xorAll ^= numXOR all elements in the array to cancel out present numbers
int setBit = xorAll & (-xorAll)Find rightmost set bit to partition
int x = 0, y = 0Initialize variables to hold the two missing numbers
for (int i = 1; i <= n; i++) { if ((i & setBit) != 0) x ^= i; else y ^= i; }Partition numbers based on set bit and XOR separately
for (int num : arr) { if ((num & setBit) != 0) x ^= num; else y ^= num; }Partition array elements similarly to cancel out present numbers
return new int[]{x, y}Return the two missing numbers
#include <iostream>
#include <vector>
using namespace std;
vector<int> findTwoMissingXOR(int n, vector<int>& arr) {
int xorAll = 0;
for (int i = 1; i <= n; i++) xorAll ^= i;
for (int num : arr) xorAll ^= num;
int setBit = xorAll & (-xorAll);
int x = 0, y = 0;
for (int i = 1; i <= n; i++) {
if (i & setBit) x ^= i;
else y ^= i;
}
for (int num : arr) {
if (num & setBit) x ^= num;
else y ^= num;
}
return {x, y};
}
int main() {
int n = 6;
vector<int> arr = {1, 2, 4, 6};
vector<int> res = findTwoMissingXOR(n, arr);
cout << res[0] << " " << res[1] << endl;
return 0;
}
Line Notes
int xorAll = 0Initialize XOR accumulator
for (int i = 1; i <= n; i++) xorAll ^= iXOR all numbers from 1 to n
for (int num : arr) xorAll ^= numXOR all elements in the array to cancel out present numbers
int setBit = xorAll & (-xorAll)Find rightmost set bit to partition
int x = 0, y = 0Initialize variables to hold the two missing numbers
for (int i = 1; i <= n; i++) { if (i & setBit) x ^= i; else y ^= i; }Partition numbers based on set bit and XOR separately
for (int num : arr) { if (num & setBit) x ^= num; else y ^= num; }Partition array elements similarly to cancel out present numbers
return {x, y}Return the two missing numbers
function findTwoMissingXOR(n, arr) {
let xorAll = 0;
for (let i = 1; i <= n; i++) xorAll ^= i;
for (let num of arr) xorAll ^= num;
let setBit = xorAll & (-xorAll);
let x = 0, y = 0;
for (let i = 1; i <= n; i++) {
if ((i & setBit) !== 0) x ^= i;
else y ^= i;
}
for (let num of arr) {
if ((num & setBit) !== 0) x ^= num;
else y ^= num;
}
return [x, y];
}
// Test
console.log(findTwoMissingXOR(6, [1, 2, 4, 6]));
Line Notes
let xorAll = 0Initialize XOR accumulator
for (let i = 1; i <= n; i++) xorAll ^= iXOR all numbers from 1 to n
for (let num of arr) xorAll ^= numXOR all elements in the array to cancel out present numbers
let setBit = xorAll & (-xorAll)Find rightmost set bit to partition
let x = 0, y = 0Initialize variables to hold the two missing numbers
for (let i = 1; i <= n; i++) { if ((i & setBit) !== 0) x ^= i; else y ^= i; }Partition numbers based on set bit and XOR separately
for (let num of arr) { if ((num & setBit) !== 0) x ^= num; else y ^= num; }Partition array elements similarly to cancel out present numbers
return [x, y]Return the two missing numbers
We do two passes over the range and array, each O(n). Space is constant for variables.
💡 For n=100000, this means about 200000 operations, very efficient for interviews.
Interview Verdict: Accepted / Optimal approach
This is the best approach to implement in interviews due to its efficiency and elegance.