Given an array arr[] of positive integers, find the maximum XOR value obtainable by taking the XOR of any subset of its elements.
Examples:
Input: arr[] = [2, 4, 5]
Output: 7
Explanation: The subset {2, 5} has the maximum XOR value.Input: arr[] = [9, 8, 5]
Output: 13
Explanation: The subset {8, 5} has the maximum XOR value.
Try It Yourself
Table of Content
[Naive Approach] By generating all possible subsets - O(2^n × n) Time and O(1) Space
Generate all subsets, compute the XOR of elements in each subset, and keep track of the maximum XOR value obtained.
Since a subset can either include or exclude each element, there are 2n possible subsets of an array of size n.
#include <bits/stdc++.h>
using namespace std;
// Returns the maximum XOR value
// obtainable from any subset.
int maxSubsetXOR(vector<int> &arr) {
int n = arr.size();
int ans = 0;
// Generate all possible subsets.
for (int mask = 0; mask < (1 << n); mask++) {
int currXor = 0;
// Compute XOR of the current subset.
for (int i = 0; i < n; i++) {
if (mask & (1 << i)) {
currXor ^= arr[i];
}
}
ans = max(ans, currXor);
}
return ans;
}
int main() {
vector<int> arr = {2, 4, 5};
cout << maxSubsetXOR(arr);
return 0;
}
public class GFG {
// Returns the maximum XOR value
// obtainable from any subset.
static int maxSubsetXOR(int[] arr) {
int n = arr.length;
int ans = 0;
// Generate all possible subsets.
for (int mask = 0; mask < (1 << n); mask++) {
int currXor = 0;
// Compute XOR of the current subset.
for (int i = 0; i < n; i++) {
if ((mask & (1 << i)) != 0) {
currXor ^= arr[i];
}
}
ans = Math.max(ans, currXor);
}
return ans;
}
public static void main(String[] args) {
int[] arr = {2, 4, 5};
System.out.println(maxSubsetXOR(arr));
}
}
# Returns the maximum XOR value
# obtainable from any subset.
def maxSubsetXOR(arr):
n = len(arr)
ans = 0
# Generate all possible subsets.
for mask in range(1 << n):
curr_xor = 0
# Compute XOR of the current subset.
for i in range(n):
if mask & (1 << i):
curr_xor ^= arr[i]
ans = max(ans, curr_xor)
return ans
if __name__ == "__main__":
arr = [2, 4, 5]
print(maxSubsetXOR(arr))
using System;
class GFG
{
// Returns the maximum XOR value
// obtainable from any subset.
static int maxSubsetXOR(int[] arr)
{
int n = arr.Length;
int ans = 0;
// Generate all possible subsets.
for (int mask = 0; mask < (1 << n); mask++)
{
int currXor = 0;
// Compute XOR of the current subset.
for (int i = 0; i < n; i++)
{
if ((mask & (1 << i)) != 0)
{
currXor ^= arr[i];
}
}
ans = Math.Max(ans, currXor);
}
return ans;
}
static void Main()
{
int[] arr = { 2, 4, 5 };
Console.WriteLine(maxSubsetXOR(arr));
}
}
// Returns the maximum XOR value
// obtainable from any subset.
function maxSubsetXOR(arr) {
const n = arr.length;
let ans = 0;
// Generate all possible subsets.
for (let mask = 0; mask < (1 << n); mask++) {
let currXor = 0;
// Compute XOR of the current subset.
for (let i = 0; i < n; i++) {
if (mask & (1 << i)) {
currXor ^= arr[i];
}
}
ans = Math.max(ans, currXor);
}
return ans;
}
// Driver Code
const arr = [2, 4, 5];
console.log(maxSubsetXOR(arr));
Output
7
[Expected Approach] By applying Gaussian Elimination on Bits
The idea is based on below facts:
- Number of bits to represent all elements is fixed which is 32 bits for integer in most of the cases.
- If an element has Most Significant Bit MSB at position i, then result is at least 2i
Steps
- Process bits from the most significant bit to the least significant bit.
- For each bit, select an element having that bit set and make it the pivot.
- Place the pivot at the current basis position so that it is not considered again. Note that we modify the same array to have the XOR subset elements.
- Eliminate the current bit from all other elements using XOR so that when we finally do XOR of the array, these elements are not considered.
- Return XOR of the modified array.
#include <bits/stdc++.h>
using namespace std;
// Returns the maximum XOR value
// obtainable from any subset.
int maxSubsetXOR(vector<int> &arr) {
int n = arr.size();
int index = 0;
// Process bits from MSB to LSB.
for (int bit = 31; bit >= 0 && index < n; bit--) {
int maxIndex = index;
// Find an element having the current bit set.
for (int i = index; i < n; i++) {
if ((arr[i] & (1 << bit)) &&
arr[i] > arr[maxIndex]) {
maxIndex = i;
}
}
// No pivot found for this bit.
if ((arr[maxIndex] & (1 << bit)) == 0) {
continue;
}
// Place the pivot at the current index.
swap(arr[index], arr[maxIndex]);
// Eliminate the current bit from all other elements.
for (int i = 0; i < n; i++) {
if (i != index &&
(arr[i] & (1 << bit))) {
arr[i] ^= arr[index];
}
}
index++;
}
// XOR of all basis elements gives
// the maximum subset XOR.
int ans = 0;
for (int num : arr) {
ans ^= num;
}
return ans;
}
int main() {
vector<int> arr = {2, 4, 5};
cout << maxSubsetXOR(arr);
return 0;
}
public class GFG {
// Returns the maximum XOR value
// obtainable from any subset.
static int maxSubsetXOR(int[] arr) {
int n = arr.length;
int index = 0;
// Process bits from MSB to LSB.
for (int bit = 31; bit >= 0 && index < n; bit--) {
int maxIndex = index;
// Find an element having the current bit set.
for (int i = index; i < n; i++) {
if ((arr[i] & (1 << bit)) != 0 &&
arr[i] > arr[maxIndex]) {
maxIndex = i;
}
}
// No pivot found for this bit.
if ((arr[maxIndex] & (1 << bit)) == 0) {
continue;
}
// Place the pivot at the current index.
int temp = arr[index];
arr[index] = arr[maxIndex];
arr[maxIndex] = temp;
// Eliminate the current bit from all other elements.
for (int i = 0; i < n; i++) {
if (i != index &&
(arr[i] & (1 << bit)) != 0) {
arr[i] ^= arr[index];
}
}
index++;
}
int ans = 0;
for (int num : arr) {
ans ^= num;
}
return ans;
}
public static void main(String[] args) {
int[] arr = {2, 4, 5};
System.out.println(maxSubsetXOR(arr));
}
}
# Returns the maximum XOR value
# obtainable from any subset.
def maxSubsetXOR(arr):
n = len(arr)
index = 0
# Process bits from MSB to LSB.
for bit in range(31, -1, -1):
if index >= n:
break
max_index = index
# Find an element having the current bit set.
for i in range(index, n):
if (arr[i] & (1 << bit)) and \
arr[i] > arr[max_index]:
max_index = i
# No pivot found for this bit.
if (arr[max_index] & (1 << bit)) == 0:
continue
# Place the pivot at the current index.
arr[index], arr[max_index] = \
arr[max_index], arr[index]
# Eliminate the current bit from all other elements.
for i in range(n):
if i != index and \
(arr[i] & (1 << bit)):
arr[i] ^= arr[index]
index += 1
ans = 0
for num in arr:
ans ^= num
return ans
arr = [2, 4, 5]
print(maxSubsetXOR(arr))
using System;
class GFG
{
// Returns the maximum XOR value
// obtainable from any subset.
static int maxSubsetXOR(int[] arr)
{
int n = arr.Length;
int index = 0;
// Process bits from MSB to LSB.
for (int bit = 31; bit >= 0 && index < n; bit--)
{
int maxIndex = index;
// Find an element having the current bit set.
for (int i = index; i < n; i++)
{
if ((arr[i] & (1 << bit)) != 0 &&
arr[i] > arr[maxIndex])
{
maxIndex = i;
}
}
// No pivot found for this bit.
if ((arr[maxIndex] & (1 << bit)) == 0)
{
continue;
}
// Place the pivot at the current index.
int temp = arr[index];
arr[index] = arr[maxIndex];
arr[maxIndex] = temp;
// Eliminate the current bit from all other elements.
for (int i = 0; i < n; i++)
{
if (i != index &&
(arr[i] & (1 << bit)) != 0)
{
arr[i] ^= arr[index];
}
}
index++;
}
int ans = 0;
foreach (int num in arr)
{
ans ^= num;
}
return ans;
}
static void Main()
{
int[] arr = { 2, 4, 5 };
Console.WriteLine(maxSubsetXOR(arr));
}
}
// Returns the maximum XOR value
// obtainable from any subset.
function maxSubsetXOR(arr) {
const n = arr.length;
let index = 0;
// Process bits from MSB to LSB.
for (let bit = 31; bit >= 0 && index < n; bit--) {
let maxIndex = index;
// Find an element having the current bit set.
for (let i = index; i < n; i++) {
if ((arr[i] & (1 << bit)) !== 0 &&
arr[i] > arr[maxIndex]) {
maxIndex = i;
}
}
// No pivot found for this bit.
if ((arr[maxIndex] & (1 << bit)) === 0) {
continue;
}
// Place the pivot at the current index.
[arr[index], arr[maxIndex]] =
[arr[maxIndex], arr[index]];
// Eliminate the current bit from all other elements.
for (let i = 0; i < n; i++) {
if (i !== index &&
(arr[i] & (1 << bit)) !== 0) {
arr[i] ^= arr[index];
}
}
index++;
}
let ans = 0;
for (const num of arr) {
ans ^= num;
}
return ans;
}
// Driver Code
const arr = [2, 4, 5];
console.log(maxSubsetXOR(arr));
Output
7
Time Complexity: O(n × log(max(arr))) - For each bit position, all n elements may be processed once.
Auxiliary Space: O(1)