Maximize Bitwise XOR of K with two numbers from Array
Last Updated :
21 Feb, 2023
Given an integer K and an array arr[] of size N, the task is to choose two elements from the array in such a way that the Bitwise XOR of those two with K (i.e. K ⊕ First chosen element ⊕ Second chosen element) is the maximum.
Note: Any array element can be chosen as many times as possible
Examples:
Input: N = 3, K = 2, arr[]= [1, 2, 3]
Output: 3
Explanation: If we choose one element from the second index
and another one from the third index, then the XOR of triplet
will be 2 ^ 2 ^ 3 = 3, which is the maximum possible.
Input: N = 3, K = 7, arr[] = [4, 2, 3]
Output: 7
Explanation: If we choose both the element from the third index,
then the XOR of triplet will be 7 ^ 3 ^ 3 = 7, which is the maximum possible.
Input: N = 3, K = 3, arr[] = [1, 2, 3]
Output: 3
Explanation: If we choose both the element from the third index,
then the XOR of triplet will be 3 ^ 3 ^ 3 = 3, which is the maximum possible.
Naive Approach: The approach to the problem is to:
Iterate over all the unique pairs in the array and find the xor value of the triplet and keep track of the maximum.
Follow the steps mentioned below to implement the above idea:
- Use two nested loops for generating all the unique pairs.
- Find the xor of the each triplets arr[i] ⊕ arr[j] ⊕ K.
- Find the maximum of xor for each pair.
- At the end return the maximum xor value obtained.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxXor(vector< int >& v, int k)
{
int n = v.size(), ans = 0;
for ( int i = 0; i < n; i++) {
for ( int j = i; j < n; j++) {
ans = max(ans, v[i] ^ v[j] ^ k);
}
}
return ans;
}
int main()
{
int N = 3, K = 2;
vector< int > arr = { 1, 2, 3 };
cout << maxXor(arr, K);
return 0;
}
|
Java
import java.util.*;
class GFG {
public static int maxXor( int v[], int k)
{
int n = v.length, ans = 0 ;
for ( int i = 0 ; i < n; i++) {
for ( int j = i; j < n; j++) {
ans = Math.max(ans, v[i] ^ v[j] ^ k);
}
}
return ans;
}
public static void main(String[] args)
{
int N = 3 , K = 2 ;
int [] arr = new int [] { 1 , 2 , 3 };
System.out.print(maxXor(arr, K));
}
}
|
Python3
def maxXor(v, k):
n, ans = len (v), 0
for i in range (n):
for j in range (i, n):
ans = max (ans, v[i] ^ v[j] ^ k)
return ans
N, K = 3 , 2
arr = [ 1 , 2 , 3 ]
print (maxXor(arr, K))
|
C#
using System;
class GFG
{
static int maxXor( int [] v, int k)
{
int n = v.Length, ans = 0;
for ( int i = 0; i < n; i++) {
for ( int j = i; j < n; j++) {
ans = Math.Max(ans, v[i] ^ v[j] ^ k);
}
}
return ans;
}
public static void Main()
{
int N = 3, K = 2;
int [] arr = { 1, 2, 3 };
Console.Write(maxXor(arr, K));
}
}
|
Javascript
<script>
function maxXor(v, k) {
let n = v.length, ans = 0;
for (let i = 0; i < n; i++) {
for (let j = i; j < n; j++) {
ans = Math.max(ans, v[i] ^ v[j] ^ k);
}
}
return ans;
}
let N = 3, K = 2;
let arr = [1, 2, 3];
document.write(maxXor(arr, K));
</script>
|
Time Complexity: O(N * N)
Auxiliary Space: O(1)
Efficient Approach: The problem can be efficiently solved using Trie data structure based on the following idea:
- To maximize the xor of the triplet iterate over all the elements considering them as the second element. and choose the third element efficiently in such a way that the xor of triplet is maximum possible.
- Maximize the XOR by choosing the other elements in such a way that the resultant bit is 1 most of the time, and give priority to the MSB first then to the LSB because the contribution of MSB is always greater than the LSB in final decimal value.
- For this, traverse from the MSB to LSB and if the bit is set then we will search for 0 so that the resultant bit is 1 and vice versa.
- Use Trie data structure. Because in order to maximize the xor value, we need to do the prefix search for the complement of that number, which can be done efficiently using trie.
Follow the below steps to solve this problem:
- Firstly add all the elements to the trie.
- Every bit in a number has 2 possibilities: 0 & 1, So, we have 2 pointers in every Trie Node:
- child[0] -> pointing to 0 bit &
- child[1] -> pointing to 1 bit.
- Now insert all the elements into the trie.
- Use a bitset of size 32 (bitset<32> B) and go from the most significant bit (MSB) to the least significant bit (LSB).
- Now start at the root of the Trie and check if child[0] or child[1] is present (not NULL), depending upon the current bit B[j] (j ranges from 0 to the total number bit) of the number.
- If it’s present, go to its child, if not, create a new Node at that child (0 bit or 1 bit) and move to its child.
- Now traverse the array and consider each element as the second chosen element.
- Till now the current XOR value of the triplet is K ^ arr[i].
- Now find the third element using trie such that its xor with current xor is maximum.
- Start at the root of the Trie and at the MSB of the number (initialize ans = 0 to store the answer).
- If the current bit is set in the current xor, go to child[0] to check if it’s not NULL.
- If it’s not NULL, add 2i-1 to ans (because this bit will be set in the answer), else go to child[1].
- If it’s not set, go to child[1] to see it’s not NULL.
- If it’s not NULL, we add 2i-1 to ans, else we go to child[0].
- Find the maximum (say maxi) among the maximum possible xor at each index.
- Return maxi as the answer.
Below is the implementation of the above approach :
C++
#include <bits/stdc++.h>
using namespace std;
class TrieNode {
public :
TrieNode* child[2];
TrieNode()
{
this ->child[0] = NULL;
this ->child[1] = NULL;
}
};
TrieNode* newNode;
void insert( int x)
{
TrieNode* t = newNode;
bitset<32> bs(x);
for ( int j = 30; j >= 0; j--) {
if (!t->child[bs[j]]) {
t->child[bs[j]]
= new TrieNode();
}
t = t->child[bs[j]];
}
}
int findMaxXor( int k)
{
TrieNode* t = newNode;
bitset<32> bs(k);
int ans = 0;
for ( int j = 30; j >= 0; j--) {
if (t->child[!bs[j]]) {
ans += (1 << j), t = t->child[!bs[j]];
}
else {
t = t->child[bs[j]];
}
}
return ans;
}
int maxXor(vector< int >& v, int K)
{
int n = v.size();
newNode = new TrieNode();
for ( int i = 0; i < n; i++) {
insert(v[i]);
}
int ans = 0;
for ( int i = 0; i < n; i++) {
ans = max(ans, findMaxXor(v[i] ^ K));
}
return ans;
}
int main()
{
int N = 3, K = 2;
vector< int > arr = { 1, 2, 3 };
cout << maxXor(arr, K);
return 0;
}
|
Java
import java.util.BitSet;
import java.util.Vector;
public class Trie {
static class TrieNode {
TrieNode[] child = new TrieNode[ 2 ];
TrieNode() {
this .child[ 0 ] = null ;
this .child[ 1 ] = null ;
}
}
static TrieNode newNode;
static void insert( int x) {
TrieNode t = newNode;
BitSet bs = BitSet.valueOf( new long [] { x });
for ( int j = 30 ; j >= 0 ; j--) {
if (t.child[bs.get(j) ? 1 : 0 ] == null ) {
t.child[bs.get(j) ? 1 : 0 ] = new TrieNode();
}
t = t.child[bs.get(j) ? 1 : 0 ];
}
}
static int findMaxXor( int k) {
TrieNode t = newNode;
BitSet bs = BitSet.valueOf( new long [] { k });
int ans = 0 ;
for ( int j = 30 ; j >= 0 ; j--) {
if (t.child[bs.get(j) ? 0 : 1 ] != null ) {
ans += ( 1 << j);
t = t.child[bs.get(j) ? 0 : 1 ];
} else {
t = t.child[bs.get(j) ? 1 : 0 ];
}
}
return ans;
}
static int maxXor(Vector<Integer> v, int K) {
int n = v.size();
newNode = new TrieNode();
for ( int i = 0 ; i < n; i++) {
insert(v.get(i));
}
int ans = 0 ;
for ( int i = 0 ; i < n; i++) {
ans = Math.max(ans, findMaxXor(v.get(i) ^ K));
}
return ans;
}
public static void main(String[] args) {
int N = 3 , K = 2 ;
Vector<Integer> arr = new Vector<>();
arr.add( 1 );
arr.add( 2 );
arr.add( 3 );
System.out.println(maxXor(arr, K));
}
}
|
Python3
from typing import List
class TrieNode:
def __init__( self ):
self .child = [ None , None ]
def insert(root: TrieNode, x: int ) - > None :
for j in range ( 30 , - 1 , - 1 ):
bit = (x >> j) & 1
if root.child[bit] is None :
root.child[bit] = TrieNode()
root = root.child[bit]
def findMaxXor(root: TrieNode, k: int ) - > int :
ans = 0
for j in range ( 30 , - 1 , - 1 ):
bit = (k >> j) & 1
if root.child[ 1 - bit] is not None :
ans + = ( 1 << j)
root = root.child[ 1 - bit]
else :
root = root.child[bit]
return ans
def maxXor(arr: List [ int ], k: int ) - > int :
n = len (arr)
root = TrieNode()
for i in range (n):
insert(root, arr[i])
ans = 0
for i in range (n):
ans = max (ans, findMaxXor(root, arr[i] ^ k))
return ans
if __name__ = = '__main__' :
arr = [ 1 , 2 , 3 ]
K = 2
print (maxXor(arr, K))
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
public class Trie
{
private class TrieNode
{
public TrieNode[] child = new TrieNode[2];
public TrieNode()
{
this .child[0] = null ;
this .child[1] = null ;
}
}
private static TrieNode newNode;
private static void Insert( int x)
{
TrieNode t = newNode;
BitArray bs = new BitArray( new int [] { x });
for ( int j = 30; j >= 0; j--)
{
if (t.child[bs.Get(j) ? 1 : 0] == null )
{
t.child[bs.Get(j) ? 1 : 0] = new TrieNode();
}
t = t.child[bs.Get(j) ? 1 : 0];
}
}
private static int FindMaxXor( int k)
{
TrieNode t = newNode;
BitArray bs = new BitArray( new int [] { k });
int ans = 0;
for ( int j = 30; j >= 0; j--)
{
if (t.child[bs.Get(j) ? 0 : 1] != null )
{
ans += (1 << j);
t = t.child[bs.Get(j) ? 0 : 1];
}
else
{
t = t.child[bs.Get(j) ? 1 : 0];
}
}
return ans;
}
public static int MaxXor(List< int > v, int K)
{
int n = v.Count;
newNode = new TrieNode();
for ( int i = 0; i < n; i++)
{
Insert(v[i]);
}
int ans = 0;
for ( int i = 0; i < n; i++)
{
ans = Math.Max(ans, FindMaxXor(v[i] ^ K));
}
return ans;
}
public static void Main()
{
int N = 3, K = 2;
List< int > arr = new List< int > { 1, 2, 3 };
Console.WriteLine(MaxXor(arr, K));
}
}
|
Javascript
class TrieNode {
constructor()
{
this .child = new Array(2);
this .child[0] = null ;
this .child[1] = null ;
}
}
let newNode = null ;
function insert(x)
{
let t = newNode;
let bs = x.toString(2);
for (let i = bs.length; i < 32; i++){
bs = bs + '0' ;
}
for (let j = 30; j >= 0; j--) {
let index = bs[j].charCodeAt(0) - '0' .charCodeAt(0);
if (t.child[index] == null ) {
t.child[index] = new TrieNode();
}
t = t.child[index];
}
}
function findMaxXor(k)
{
let t = newNode;
let bs = k.toString(2);
for (let i = bs.length; i < 32; i++){
bs = bs + '0' ;
}
let ans = 0;
for (let j = 30; j >= 0; j--) {
let index = bs[j].charCodeAt(0) - '0' .charCodeAt(0);
let nindex;
if (index == 0) nindex = 1;
else nindex = 0;
if (t.child[nindex]) {
ans = ans + (1 << j);
t = t.child[nindex];
}
else {
t = t.child[index];
}
}
return ans;
}
function maxXor(v, K)
{
let n = v.length;
newNode = new TrieNode();
for (let i = 0; i < n; i++) {
insert(v[i]);
}
let ans = 0;
for (let i = 0; i < n; i++) {
ans = Math.max(ans, findMaxXor(v[i]^K));
}
return ans;
}
let N = 3;
let K = 2;
let arr = [ 1, 2, 3 ];
console.log(maxXor(arr, K));
|
Time Complexity: O(N * logM) where M is the maximum element of the array.
Auxiliary Space: O(logM)
Share your thoughts in the comments
Please Login to comment...