Given an array of integers, find minimum XOR value of a pain in the array.
Examples :
Input: arr[] = [9 5 3]
Output: 6
Explanation: The XOR values of all possible pairs are 9 ^ 5 = 12, 9 ^ 3 = 10, and 5 ^ 3 = 6. Therefore, the minimum XOR value is 6.Input: arr[] = [6 1 4 2]
Output: 2
Explanation: Among all pairs, the minimum XOR value is obtained from 6 ^ 4 = 2.
Table of Content
[Naive Approach] Check All Pairs - O(n²) Time and O(1) Space
A straightforward approach is to compute the XOR value for every possible pair and keep track of the minimum XOR encountered. After checking all pairs, the stored minimum value is the answer.
#include <bits/stdc++.h>
using namespace std;
// Return the minimum XOR value among all pairs.
int minXor(vector<int> &arr) {
int n = arr.size();
int res = INT_MAX;
// Check XOR of every pair.
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
res = min(res, arr[i] ^ arr[j]);
}
}
return res;
}
int main() {
vector<int> arr = {9, 5, 3};
cout << minXor(arr);
return 0;
}
public class GFG {
// Return the minimum XOR value among all pairs.
static int minXor(int[] arr) {
int n = arr.length;
int res = Integer.MAX_VALUE;
// Check XOR of every pair.
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
res = Math.min(res, arr[i] ^ arr[j]);
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {9, 5, 3};
System.out.println(minXor(arr));
}
}
# Return the minimum XOR value among all pairs.
def min_xor(arr):
n = len(arr)
res = float('inf')
# Check XOR of every pair.
for i in range(n):
for j in range(i + 1, n):
res = min(res, arr[i] ^ arr[j])
return res
if __name__ == "__main__":
arr = [9, 5, 3]
print(min_xor(arr))
using System;
class GFG
{
// Return the minimum XOR value among all pairs.
static int MinXor(int[] arr)
{
int n = arr.Length;
int res = int.MaxValue;
// Check XOR of every pair.
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
res = Math.Min(res, arr[i] ^ arr[j]);
}
}
return res;
}
static void Main()
{
int[] arr = { 9, 5, 3 };
Console.WriteLine(MinXor(arr));
}
}
// Return the minimum XOR value among all pairs.
function minXor(arr) {
const n = arr.length;
let res = Number.MAX_SAFE_INTEGER;
// Check XOR of every pair.
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
res = Math.min(res, arr[i] ^ arr[j]);
}
}
return res;
}
// Driver Code
const arr = [9, 5, 3];
console.log(minXor(arr));
Output
6
[Better Approach] Sorting and Checking Adjacent Pairs - O(n log n) Time and O(1) Space
To obtain a small XOR value, two numbers should differ in as few bits as possible. After sorting, numbers with similar binary representations become adjacent. Therefore, the minimum XOR pair must occur among neighboring elements in the sorted array.
#include <bits/stdc++.h>
using namespace std;
// Return the minimum XOR value among all pairs.
int minXor(vector<int> &arr) {
sort(arr.begin(), arr.end());
int res = INT_MAX;
// Check XOR of adjacent pairs.
for (int i = 1; i < arr.size(); i++) {
res = min(res, arr[i] ^ arr[i - 1]);
}
return res;
}
int main() {
vector<int> arr = {9, 5, 3};
cout << minXor(arr);
return 0;
}
import java.util.Arrays;
public class GFG {
// Return the minimum XOR value among all pairs.
static int minXor(int[] arr) {
Arrays.sort(arr);
int res = Integer.MAX_VALUE;
// Check XOR of adjacent pairs.
for (int i = 1; i < arr.length; i++) {
res = Math.min(res, arr[i] ^ arr[i - 1]);
}
return res;
}
public static void main(String[] args) {
int[] arr = {9, 5, 3};
System.out.println(minXor(arr));
}
}
# Return the minimum XOR value among all pairs.
def min_xor(arr):
arr.sort()
res = float('inf')
# Check XOR of adjacent pairs.
for i in range(1, len(arr)):
res = min(res, arr[i] ^ arr[i - 1])
return res
if __name__ == "__main__":
arr = [9, 5, 3]
print(min_xor(arr))
using System;
class GFG
{
// Return the minimum XOR value among all pairs.
static int MinXor(int[] arr)
{
Array.Sort(arr);
int res = int.MaxValue;
// Check XOR of adjacent pairs.
for (int i = 1; i < arr.Length; i++)
{
res = Math.Min(res, arr[i] ^ arr[i - 1]);
}
return res;
}
static void Main()
{
int[] arr = { 9, 5, 3 };
Console.WriteLine(MinXor(arr));
}
}
// Return the minimum XOR value among all pairs.
function minXor(arr) {
arr.sort((a, b) => a - b);
let res = Number.MAX_SAFE_INTEGER;
// Check XOR of adjacent pairs.
for (let i = 1; i < arr.length; i++) {
res = Math.min(res, arr[i] ^ arr[i - 1]);
}
return res;
}
// Driver Code
const arr = [9, 5, 3];
console.log(minXor(arr));
Output
6
[Expected Approach] Using Trie - O(n) Time and O(n) Space
To minimize the XOR value, we try to match as many bits as possible. A Bitwise Trie stores the binary representation of previously seen numbers. For each number, we traverse the Trie preferring the same bit at every position, which minimizes the resulting XOR. The minimum XOR obtained over all such pairs is the answer.
Steps
- Create an empty Bitwise Trie and insert the first element of the array into it.
- For each remaining element, traverse the Trie preferring the same bit at every position to obtain the minimum XOR value with a previously inserted element.
- Update the answer if the computed XOR value is smaller than the current minimum.
- Insert the current element into the Trie for future comparisons.
- Repeat the process for all elements in the array.
- Return the minimum XOR value obtained.
#include <bits/stdc++.h>
using namespace std;
const int BITS = 31;
struct TrieNode {
TrieNode* child[2];
TrieNode() {
child[0] = child[1] = nullptr;
}
};
// Insert a number into the Trie.
void insert(TrieNode* root, int num) {
TrieNode* curr = root;
for (int i = BITS; i >= 0; i--) {
int bit = (num >> i) & 1;
if (!curr->child[bit]) {
curr->child[bit] = new TrieNode();
}
curr = curr->child[bit];
}
}
// Return the minimum XOR value of num
// with any number already present in the Trie.
int getMinXor(TrieNode* root, int num) {
TrieNode* curr = root;
int xorValue = 0;
for (int i = BITS; i >= 0; i--) {
int bit = (num >> i) & 1;
// Prefer the same bit to minimize XOR.
if (curr->child[bit]) {
curr = curr->child[bit];
} else {
xorValue |= (1 << i);
curr = curr->child[1 - bit];
}
}
return xorValue;
}
// Return the minimum XOR value among all pairs.
int minXor(vector<int>& arr) {
TrieNode* root = new TrieNode();
// Insert the first element into the Trie.
insert(root, arr[0]);
int res = INT_MAX;
for (int i = 1; i < arr.size(); i++) {
res = min(res, getMinXor(root, arr[i]));
// Insert the current element into the Trie.
insert(root, arr[i]);
}
return res;
}
int main() {
vector<int> arr = {9, 5, 3};
cout << minXor(arr);
return 0;
}
public class GFG {
private static final int BITS = 31;
static class TrieNode {
TrieNode[] child;
TrieNode() {
child = new TrieNode[2];
}
}
// Insert a number into the Trie.
static void insert(TrieNode root, int num) {
TrieNode curr = root;
for (int i = BITS; i >= 0; i--) {
int bit = (num >> i) & 1;
if (curr.child[bit] == null) {
curr.child[bit] = new TrieNode();
}
curr = curr.child[bit];
}
}
// Return the minimum XOR value of num
// with any number already present in the Trie.
static int getMinXor(TrieNode root, int num) {
TrieNode curr = root;
int xorValue = 0;
for (int i = BITS; i >= 0; i--) {
int bit = (num >> i) & 1;
// Prefer the same bit to minimize XOR.
if (curr.child[bit] != null) {
curr = curr.child[bit];
} else {
xorValue |= (1 << i);
curr = curr.child[1 - bit];
}
}
return xorValue;
}
// Return the minimum XOR value among all pairs.
static int minXor(int[] arr) {
TrieNode root = new TrieNode();
// Insert the first element into the Trie.
insert(root, arr[0]);
int res = Integer.MAX_VALUE;
for (int i = 1; i < arr.length; i++) {
res = Math.min(res, getMinXor(root, arr[i]));
// Insert the current element into the Trie.
insert(root, arr[i]);
}
return res;
}
public static void main(String[] args) {
int[] arr = {9, 5, 3};
System.out.println(minXor(arr));
}
}
BITS = 31
class TrieNode:
def __init__(self):
self.child = [None, None]
# Insert a number into the Trie.
def insert(root, num):
curr = root
for i in range(BITS, -1, -1):
bit = (num >> i) & 1
if curr.child[bit] is None:
curr.child[bit] = TrieNode()
curr = curr.child[bit]
# Return the minimum XOR value of num
# with any number already present in the Trie.
def get_min_xor(root, num):
curr = root
xor_value = 0
for i in range(BITS, -1, -1):
bit = (num >> i) & 1
# Prefer the same bit to minimize XOR.
if curr.child[bit] is not None:
curr = curr.child[bit]
else:
xor_value |= (1 << i)
curr = curr.child[1 - bit]
return xor_value
# Return the minimum XOR value among all pairs.
def min_xor(arr):
root = TrieNode()
# Insert the first element into the Trie.
insert(root, arr[0])
res = float('inf')
for i in range(1, len(arr)):
res = min(res, get_min_xor(root, arr[i]))
# Insert the current element into the Trie.
insert(root, arr[i])
return res
if __name__ == "__main__":
arr = [9, 5, 3]
print(min_xor(arr))
using System;
class GFG
{
private const int BITS = 31;
class TrieNode
{
public TrieNode[] child;
public TrieNode()
{
child = new TrieNode[2];
}
}
// Insert a number into the Trie.
static void Insert(TrieNode root, int num)
{
TrieNode curr = root;
for (int i = BITS; i >= 0; i--)
{
int bit = (num >> i) & 1;
if (curr.child[bit] == null)
{
curr.child[bit] = new TrieNode();
}
curr = curr.child[bit];
}
}
// Return the minimum XOR value of num
// with any number already present in the Trie.
static int GetMinXor(TrieNode root, int num)
{
TrieNode curr = root;
int xorValue = 0;
for (int i = BITS; i >= 0; i--)
{
int bit = (num >> i) & 1;
// Prefer the same bit to minimize XOR.
if (curr.child[bit] != null)
{
curr = curr.child[bit];
}
else
{
xorValue |= (1 << i);
curr = curr.child[1 - bit];
}
}
return xorValue;
}
// Return the minimum XOR value among all pairs.
static int MinXor(int[] arr)
{
TrieNode root = new TrieNode();
// Insert the first element into the Trie.
Insert(root, arr[0]);
int res = int.MaxValue;
for (int i = 1; i < arr.Length; i++)
{
res = Math.Min(res, GetMinXor(root, arr[i]));
// Insert the current element into the Trie.
Insert(root, arr[i]);
}
return res;
}
static void Main()
{
int[] arr = { 9, 5, 3 };
Console.WriteLine(MinXor(arr));
}
}
const BITS = 31;
class TrieNode {
constructor() {
this.child = [null, null];
}
}
// Insert a number into the Trie.
function insert(root, num) {
let curr = root;
for (let i = BITS; i >= 0; i--) {
const bit = (num >> i) & 1;
if (!curr.child[bit]) {
curr.child[bit] = new TrieNode();
}
curr = curr.child[bit];
}
}
// Return the minimum XOR value of num
// with any number already present in the Trie.
function getMinXor(root, num) {
let curr = root;
let xorValue = 0;
for (let i = BITS; i >= 0; i--) {
const bit = (num >> i) & 1;
// Prefer the same bit to minimize XOR.
if (curr.child[bit]) {
curr = curr.child[bit];
} else {
xorValue |= (1 << i);
curr = curr.child[1 - bit];
}
}
return xorValue;
}
// Return the minimum XOR value among all pairs.
function minXor(arr) {
const root = new TrieNode();
// Insert the first element into the Trie.
insert(root, arr[0]);
let res = Number.MAX_SAFE_INTEGER;
for (let i = 1; i < arr.length; i++) {
res = Math.min(res, getMinXor(root, arr[i]));
// Insert the current element into the Trie.
insert(root, arr[i]);
}
return res;
}
const arr = [9, 5, 3];
console.log(minXor(arr));
Output
6