Given an array Arr of non-negative integers of size N. The task is to find the maximum possible xor between two numbers present in the array.
Example:
Input: Arr = {25, 10, 2, 8, 5, 3}
Output: 28
Explanation: The maximum result is 5 ^ 25 = 28
Input: Arr = {1, 2, 3, 4, 5, 6, 7}
Output: 7
Explanation: The maximum result is 1 ^ 6 = 7
Naive Approach: A Simple Solution is to generate all pairs of the given array and compute the XOR of the pairs. Finally, return the maximum XOR value. This solution takes
time.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int max_xor( int arr[], int n)
{
int maxXor = 0;
for ( int i = 0; i < n; i++) {
for ( int j = i + 1; j < n; j++) {
maxXor = max(maxXor,
arr[i] ^ arr[j]);
}
}
return maxXor;
}
int main()
{
int arr[] = { 25, 10, 2, 8, 5, 3 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << max_xor(arr, n) << endl;
return 0;
}
|
Java
class GFG
{
static int max_xor( int arr[], int n)
{
int maxXor = 0 ;
for ( int i = 0 ; i < n; i++)
{
for ( int j = i + 1 ; j < n; j++)
{
maxXor = Math.max(maxXor,
arr[i] ^ arr[j]);
}
}
return maxXor;
}
public static void main(String[] args)
{
int arr[] = { 25 , 10 , 2 , 8 , 5 , 3 };
int n = arr.length;
System.out.println(max_xor(arr, n));
}
}
|
Python3
def max_xor(arr, n):
maxXor = 0 ;
for i in range (n):
for j in range (i + 1 , n):
maxXor = max (maxXor,\
arr[i] ^ arr[j]);
return maxXor;
if __name__ = = '__main__' :
arr = [ 25 , 10 , 2 , 8 , 5 , 3 ];
n = len (arr);
print (max_xor(arr, n));
|
C#
using System;
class GFG
{
static int max_xor( int []arr, int n)
{
int maxXor = 0;
for ( int i = 0; i < n; i++)
{
for ( int j = i + 1; j < n; j++)
{
maxXor = Math.Max(maxXor,
arr[i] ^ arr[j]);
}
}
return maxXor;
}
public static void Main()
{
int []arr = {25, 10, 2, 8, 5, 3};
int n = arr.Length;
Console.WriteLine(max_xor(arr, n));
}
}
|
Javascript
<script>
function max_xor(arr, n)
{
let maxXor = 0;
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
maxXor = Math.max(maxXor,
arr[i] ^ arr[j]);
}
}
return maxXor;
}
let arr = [ 25, 10, 2, 8, 5, 3 ];
let n = arr.length;
document.write(max_xor(arr, n));
</script>
|
Time Complexity: O(N^{2}) , where N is the size of the array
Auxiliary Space: O(1)
Efficient Approach: The approach is similar to this article where the task is to find the maximum AND value pair.
So the idea is to change the problem statement from finding the maximum xor of two numbers in an array to -> find two numbers in an array, such that xor of which equals to a number X. In this case, X will be the maximum number we want to achieve till i-th bit.
To find the largest value of an XOR operation, the value of xor should have every bit to be a set bit i.e 1. In a 32-bit number, the goal is to get the most 1 set starting left to right.
To evaluate each bit, there is a mask needed for that bit. A mask defines which bit should be present in the answer and which bit is not. Here we will use a mask to keep the prefix for every number ( means by taking the ans with the mask how many bits are remaining from the number ) in the input till the i-th bit then with the list of possible numbers in our set, after inserting the number we will evaluate if we can update the max for that bit position to be 1.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int max_xor( int arr[], int n)
{
int maxx = 0, mask = 0;
set< int > se;
for ( int i = 30; i >= 0; i--) {
mask |= (1 << i);
for ( int i = 0; i < n; ++i) {
se.insert(arr[i] & mask);
}
int newMaxx = maxx | (1 << i);
for ( int prefix : se) {
if (se.count(newMaxx ^ prefix)) {
maxx = newMaxx;
break ;
}
}
se.clear();
}
return maxx;
}
int main()
{
int arr[] = { 25, 10, 2, 8, 5, 3 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << max_xor(arr, n) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int max_xor( int arr[], int n)
{
int maxx = 0 , mask = 0 ;
HashSet<Integer> se = new HashSet<Integer>();
for ( int i = 30 ; i >= 0 ; i--)
{
mask |= ( 1 << i);
for ( int j = 0 ; j < n; ++j)
{
se.add(arr[j] & mask);
}
int newMaxx = maxx | ( 1 << i);
for ( int prefix : se)
{
if (se.contains(newMaxx ^ prefix))
{
maxx = newMaxx;
break ;
}
}
se.clear();
}
return maxx;
}
public static void main(String[] args)
{
int arr[] = { 25 , 10 , 2 , 8 , 5 , 3 };
int n = arr.length;
System.out.println(max_xor(arr, n));
}
}
|
Python3
def max_xor( arr , n):
maxx = 0
mask = 0 ;
se = set ()
for i in range ( 30 , - 1 , - 1 ):
mask | = ( 1 << i)
newMaxx = maxx | ( 1 << i)
for i in range (n):
se.add(arr[i] & mask)
for prefix in se:
if (newMaxx ^ prefix) in se:
maxx = newMaxx
break
se.clear()
return maxx
arr = [ 25 , 10 , 2 , 8 , 5 , 3 ]
n = len (arr)
print (max_xor(arr, n))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int max_xor( int []arr, int n)
{
int maxx = 0, mask = 0;
HashSet< int > se = new HashSet< int >();
for ( int i = 30; i >= 0; i--)
{
mask |= (1 << i);
for ( int j = 0; j < n; ++j)
{
se.Add(arr[j] & mask);
}
int newMaxx = maxx | (1 << i);
foreach ( int prefix in se)
{
if (se.Contains(newMaxx ^ prefix))
{
maxx = newMaxx;
break ;
}
}
se.Clear();
}
return maxx;
}
public static void Main(String[] args)
{
int []arr = { 25, 10, 2, 8, 5, 3 };
int n = arr.Length;
Console.WriteLine(max_xor(arr, n));
}
}
|
Javascript
<script>
function max_xor(arr, n)
{
let maxx = 0, mask = 0;
var se = new Set();
for (let i = 30; i >= 0; i--)
{
mask |= (1 << i);
for (let j = 0; j < n; ++j)
{
se.add(arr[j] & mask);
}
let newMaxx = maxx | (1 << i);
for (let prefix of se.keys())
{
if (se.has(newMaxx ^ prefix))
{
maxx = newMaxx;
break ;
}
}
se.clear();
}
return maxx;
}
let arr = [ 25, 10, 2, 8, 5, 3 ];
let n = arr.length;
document.write(max_xor(arr, n));
</script>
|
Time Complexity:
, where N is the size of the array and M is the maximum number present in the array
Auxiliary Space: O(logM)
Better Approach: Another approach would be to use a Trie structure to store the bit representation of the numbers and for N terms compute the maximum XOR each can produce by going through the Trie.
C++
#include <iostream>
using namespace std;
class Node {
public :
Node* one;
Node* zero;
};
class trie {
Node* root;
public :
trie() { root = new Node(); }
void insert( int n)
{
Node* temp = root;
for ( int i = 31; i >= 0; i--) {
int bit = (n >> i) & 1;
if (bit == 0) {
if (temp->zero == NULL) {
temp->zero = new Node();
}
temp = temp->zero;
}
else {
if (temp->one == NULL) {
temp->one = new Node();
}
temp = temp->one;
}
}
}
int max_xor_helper( int value)
{
Node* temp = root;
int current_ans = 0;
for ( int i = 31; i >= 0; i--) {
int bit = (value >> i) & 1;
if (bit == 0) {
if (temp->one) {
temp = temp->one;
current_ans += (1 << i);
}
else {
temp = temp->zero;
}
}
else {
if (temp->zero) {
temp = temp->zero;
current_ans += (1 << i);
}
else {
temp = temp->one;
}
}
}
return current_ans;
}
int max_xor( int arr[], int n)
{
int max_val = 0;
insert(arr[0]);
for ( int i = 1; i < n; i++) {
max_val = max(max_xor_helper(arr[i]), max_val);
insert(arr[i]);
}
return max_val;
}
};
int main()
{
int input[] = { 25, 10, 2, 8, 5, 3 };
int n = sizeof (input) / sizeof ( int );
trie t;
cout << t.max_xor(input, n);
return 0;
}
|
Java
import java.io.*;
class GFG {
static class Node {
public Node one, zero;
}
static class trie {
Node root;
public trie() { root = new Node(); }
public void insert( int n)
{
Node temp = root;
for ( int i = 31 ; i >= 0 ; i--) {
int bit = (n >> i) & 1 ;
if (bit == 0 ) {
if (temp.zero == null ) {
temp.zero = new Node();
}
temp = temp.zero;
}
else {
if (temp.one == null ) {
temp.one = new Node();
}
temp = temp.one;
}
}
}
public int max_xor_helper( int value)
{
Node temp = root;
int current_ans = 0 ;
for ( int i = 31 ; i >= 0 ; i--) {
int bit = (value >> i) & 1 ;
if (bit == 0 ) {
if (temp.one != null ) {
temp = temp.one;
current_ans += ( 1 << i);
}
else {
temp = temp.zero;
}
}
else {
if (temp.zero != null ) {
temp = temp.zero;
current_ans += ( 1 << i);
}
else {
temp = temp.one;
}
}
}
return current_ans;
}
public int max_xor( int [] arr, int n)
{
int max_val = 0 ;
insert(arr[ 0 ]);
for ( int i = 1 ; i < n; i++) {
max_val = Math.max(max_xor_helper(arr[i]),
max_val);
insert(arr[i]);
}
return max_val;
}
}
public static void main(String[] args)
{
int [] input = { 25 , 10 , 2 , 8 , 5 , 3 };
int n = input.length;
trie t = new trie();
System.out.print(t.max_xor(input, n));
}
}
|
Python3
class TrieNode :
def __init__( self ):
self .children = {}
class Trie :
def __init__( self ) :
self .root = TrieNode()
def insert( self , n) :
temp = self .root
i = 31
while i > = 0 :
bit = (n >> i) & 1
if bit not in temp.children:
temp.children[bit] = TrieNode()
temp = temp.children[bit]
i - = 1
def max_xor_helper( self , value) :
temp = self .root
current_ans = 0
i = 31
while i > = 0 :
bit = (value >> i) & 1
if bit^ 1 in temp.children:
temp = temp.children[bit^ 1 ]
current_ans + = ( 1 << i)
else :
temp = temp.children[bit]
i - = 1
return current_ans
class Solution:
def solve( self , A):
trie = Trie()
max_val = 0
trie.insert(A[ 0 ])
for n in A[ 1 :]:
max_val = max (trie.max_xor_helper(n),max_val)
trie.insert(n)
return max_val
if __name__ = = "__main__" :
A = [ 25 , 10 , 2 , 8 , 5 , 3 ]
print (Solution().solve(A))
|
C#
using System;
using System.Collections.Generic;
public class GFG {
public class Node {
public Node one;
public Node zero;
};
public class trie {
public Node root;
public trie() { root = new Node(); }
public void insert( int n)
{
Node temp = root;
for ( int i = 31; i >= 0; i--) {
int bit = (n >> i) & 1;
if (bit == 0) {
if (temp.zero == null ) {
temp.zero = new Node();
}
temp = temp.zero;
}
else {
if (temp.one == null ) {
temp.one = new Node();
}
temp = temp.one;
}
}
}
public int max_xor_helper( int value)
{
Node temp = root;
int current_ans = 0;
for ( int i = 31; i >= 0; i--) {
int bit = (value >> i) & 1;
if (bit == 0) {
if (temp.one != null ) {
temp = temp.one;
current_ans += (1 << i);
}
else {
temp = temp.zero;
}
}
else {
if (temp.zero != null ) {
temp = temp.zero;
current_ans += (1 << i);
}
else {
temp = temp.one;
}
}
}
return current_ans;
}
public int max_xor( int [] arr, int n)
{
int max_val = 0;
insert(arr[0]);
for ( int i = 1; i < n; i++) {
max_val = Math.Max(max_xor_helper(arr[i]),
max_val);
insert(arr[i]);
}
return max_val;
}
};
static public void Main()
{
int [] input = { 25, 10, 2, 8, 5, 3 };
int n = input.Length;
trie t = new trie();
Console.WriteLine(t.max_xor(input, n));
}
}
|
Javascript
class TrieNode{
constructor(){
this .children ={}
}
}
class Trie{
constructor(){
this .root = new TrieNode();
}
insert(n){
let temp = this .root;
let i = 31;
while (i >= 0){
const bit = (n >> i) & 1;
if (!temp.children[bit]) temp.children[bit] = new TrieNode()
temp = temp.children[bit]
i -= 1
}
}
max_xor_helper(value){
let temp = this .root;
let current_ans = 0;
let i = 31;
while (i >= 0){
const bit = (value >> i) & 1;
if (temp.children[bit^1]){
temp = temp.children[bit^1]
current_ans += (1 << i)
}
else temp = temp.children[bit]
i -= 1
}
return current_ans
}
}
function solve(A){
let trie = new Trie();
let max_val = 0;
trie.insert(A[0])
let i = 1;
const n = A.length;
while (i < n){
max_val = Math.max(trie.max_xor_helper(A[i]),max_val);
trie.insert(A[i]);
i += 1;
}
return max_val
}
const A = [25, 10, 2, 8, 5, 3]
console.log(solve(A))
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Please Login to comment...