给定一个整数数组。在给定数组中找到最大XOR子数组值。预期时间复杂度O(n)。
例子:
Input: arr[] = {1, 2, 3, 4}
Output: 7
The subarray {3, 4} has maximum XOR value
Input: arr[] = {8, 1, 2, 12, 7, 6}
Output: 15
The subarray {1, 2, 12} has maximum XOR value
Input: arr[] = {4, 6}
Output: 6
The subarray {6} has maximum XOR value
一个简单的解决方案是使用两个循环来查找所有子数组的XOR并返回最大值。
C++
// A simple C++ program to find max subarray XOR
#include
using namespace std;
int maxSubarrayXOR(int arr[], int n)
{
int ans = INT_MIN; // Initialize result
// Pick starting points of subarrays
for (int i=0; i
Java
// A simple Java program to find max subarray XOR
class GFG {
static int maxSubarrayXOR(int arr[], int n)
{
int ans = Integer.MIN_VALUE; // Initialize result
// Pick starting points of subarrays
for (int i=0; i
Python3
# A simple Python program
# to find max subarray XOR
def maxSubarrayXOR(arr,n):
ans = -2147483648 #Initialize result
# Pick starting points of subarrays
for i in range(n):
# to store xor of current subarray
curr_xor = 0
# Pick ending points of
# subarrays starting with i
for j in range(i,n):
curr_xor = curr_xor ^ arr[j]
ans = max(ans, curr_xor)
return ans
# Driver code
arr = [8, 1, 2, 12]
n = len(arr)
print("Max subarray XOR is ",
maxSubarrayXOR(arr, n))
# This code is contributed
# by Anant Agarwal.
C#
// A simple C# program to find
// max subarray XOR
using System;
class GFG
{
// Function to find max subarray
static int maxSubarrayXOR(int []arr, int n)
{
int ans = int.MinValue;
// Initialize result
// Pick starting points of subarrays
for (int i = 0; i < n; i++)
{
// to store xor of current subarray
int curr_xor = 0;
// Pick ending points of
// subarrays starting with i
for (int j = i; j < n; j++)
{
curr_xor = curr_xor ^ arr[j];
ans = Math.Max(ans, curr_xor);
}
}
return ans;
}
// Driver code
public static void Main()
{
int []arr = {8, 1, 2, 12};
int n = arr.Length;
Console.WriteLine("Max subarray XOR is " +
maxSubarrayXOR(arr, n));
}
}
// This code is contributed by Sam007.
PHP
Javascript
C++
// C++ program for a Trie based O(n) solution to find max
// subarray XOR
#include
using namespace std;
// Assumed int size
#define INT_SIZE 32
// A Trie Node
struct TrieNode
{
int value; // Only used in leaf nodes
TrieNode *arr[2];
};
// Utility function to create a Trie node
TrieNode *newNode()
{
TrieNode *temp = new TrieNode;
temp->value = 0;
temp->arr[0] = temp->arr[1] = NULL;
return temp;
}
// Inserts pre_xor to trie with given root
void insert(TrieNode *root, int pre_xor)
{
TrieNode *temp = root;
// Start from the msb, insert all bits of
// pre_xor into Trie
for (int i=INT_SIZE-1; i>=0; i--)
{
// Find current bit in given prefix
bool val = pre_xor & (1<arr[val] == NULL)
temp->arr[val] = newNode();
temp = temp->arr[val];
}
// Store value at leaf node
temp->value = pre_xor;
}
// Finds the maximum XOR ending with last number in
// prefix XOR 'pre_xor' and returns the XOR of this maximum
// with pre_xor which is maximum XOR ending with last element
// of pre_xor.
int query(TrieNode *root, int pre_xor)
{
TrieNode *temp = root;
for (int i=INT_SIZE-1; i>=0; i--)
{
// Find current bit in given prefix
bool val = pre_xor & (1<arr[1-val]!=NULL)
temp = temp->arr[1-val];
// If there is no prefix with opposite
// bit, then look for same bit.
else if (temp->arr[val] != NULL)
temp = temp->arr[val];
}
return pre_xor^(temp->value);
}
// Returns maximum XOR value of a subarray in arr[0..n-1]
int maxSubarrayXOR(int arr[], int n)
{
// Create a Trie and insert 0 into it
TrieNode *root = newNode();
insert(root, 0);
// Initialize answer and xor of current prefix
int result = INT_MIN, pre_xor =0;
// Traverse all input array element
for (int i=0; i
Java
// Java program for a Trie based O(n) solution to
// find max subarray XOR
class GFG
{
// Assumed int size
static final int INT_SIZE = 32;
// A Trie Node
static class TrieNode
{
int value; // Only used in leaf nodes
TrieNode[] arr = new TrieNode[2];
public TrieNode() {
value = 0;
arr[0] = null;
arr[1] = null;
}
}
static TrieNode root;
// Inserts pre_xor to trie with given root
static void insert(int pre_xor)
{
TrieNode temp = root;
// Start from the msb, insert all bits of
// pre_xor into Trie
for (int i=INT_SIZE-1; i>=0; i--)
{
// Find current bit in given prefix
int val = (pre_xor & (1<=1 ? 1 : 0;
// Create a new node if needed
if (temp.arr[val] == null)
temp.arr[val] = new TrieNode();
temp = temp.arr[val];
}
// Store value at leaf node
temp.value = pre_xor;
}
// Finds the maximum XOR ending with last number in
// prefix XOR 'pre_xor' and returns the XOR of this
// maximum with pre_xor which is maximum XOR ending
// with last element of pre_xor.
static int query(int pre_xor)
{
TrieNode temp = root;
for (int i=INT_SIZE-1; i>=0; i--)
{
// Find current bit in given prefix
int val = (pre_xor & (1<= 1 ? 1 : 0;
// Traverse Trie, first look for a
// prefix that has opposite bit
if (temp.arr[1-val] != null)
temp = temp.arr[1-val];
// If there is no prefix with opposite
// bit, then look for same bit.
else if (temp.arr[val] != null)
temp = temp.arr[val];
}
return pre_xor^(temp.value);
}
// Returns maximum XOR value of a subarray in
// arr[0..n-1]
static int maxSubarrayXOR(int arr[], int n)
{
// Create a Trie and insert 0 into it
root = new TrieNode();
insert(0);
// Initialize answer and xor of current prefix
int result = Integer.MIN_VALUE;
int pre_xor =0;
// Traverse all input array element
for (int i=0; i
Python3
"""Python implementation for a Trie based solution
to find max subArray XOR"""
"""structure of Trie Node"""
class Node:
def __init__(self, data):
self.data = data
self.left = None # left node for 0
self.right = None # right node for 1
""" class for implementing Trie """
class Trie:
def __init__(self):
self.root = Node(0)
"""insert pre_xor to trie with given root"""
def insert(self, pre_xor):
self.temp = self.root
"""start from msb, insert all bits of pre_xor
into the Trie"""
for i in range(31, -1, -1):
"""Find current bit in prefix sum"""
val = pre_xor & (1<
C#
using System;
// C# program for a Trie based O(n) solution to
// find max subarray XOR
public class GFG
{
// Assumed int size
public const int INT_SIZE = 32;
// A Trie Node
public class TrieNode
{
public int value; // Only used in leaf nodes
public TrieNode[] arr = new TrieNode[2];
public TrieNode()
{
value = 0;
arr[0] = null;
arr[1] = null;
}
}
public static TrieNode root;
// Inserts pre_xor to trie with given root
public static void insert(int pre_xor)
{
TrieNode temp = root;
// Start from the msb, insert all bits of
// pre_xor into Trie
for (int i = INT_SIZE-1; i >= 0; i--)
{
// Find current bit in given prefix
int val = (pre_xor & (1 << i)) >= 1 ? 1 : 0;
// Create a new node if needed
if (temp.arr[val] == null)
{
temp.arr[val] = new TrieNode();
}
temp = temp.arr[val];
}
// Store value at leaf node
temp.value = pre_xor;
}
// Finds the maximum XOR ending with last number in
// prefix XOR 'pre_xor' and returns the XOR of this
// maximum with pre_xor which is maximum XOR ending
// with last element of pre_xor.
public static int query(int pre_xor)
{
TrieNode temp = root;
for (int i = INT_SIZE-1; i >= 0; i--)
{
// Find current bit in given prefix
int val = (pre_xor & (1 << i)) >= 1 ? 1 : 0;
// Traverse Trie, first look for a
// prefix that has opposite bit
if (temp.arr[1 - val] != null)
{
temp = temp.arr[1 - val];
}
// If there is no prefix with opposite
// bit, then look for same bit.
else if (temp.arr[val] != null)
{
temp = temp.arr[val];
}
}
return pre_xor ^ (temp.value);
}
// Returns maximum XOR value of a subarray in
// arr[0..n-1]
public static int maxSubarrayXOR(int[] arr, int n)
{
// Create a Trie and insert 0 into it
root = new TrieNode();
insert(0);
// Initialize answer and xor of current prefix
int result = int.MinValue;
int pre_xor = 0;
// Traverse all input array element
for (int i = 0; i < n; i++)
{
// update current prefix xor and insert it
// into Trie
pre_xor = pre_xor ^ arr[i];
insert(pre_xor);
// Query for current prefix xor in Trie and
// update result if required
result = Math.Max(result, query(pre_xor));
}
return result;
}
// Driver program to test above functions
public static void Main(string[] args)
{
int[] arr = new int[] {8, 1, 2, 12};
int n = arr.Length;
Console.WriteLine("Max subarray XOR is " + maxSubarrayXOR(arr, n));
}
}
// This code is contributed by Shrikant13
输出:
Max subarray XOR is 15
上述解决方案的时间复杂度为O(n 2 )。
在整数取固定位数存储的假设下,有效解决方案可以在O(n)时间内解决上述问题。这个想法是使用Trie数据结构。下面是算法。
1) Create an empty Trie. Every node of Trie is going to
contain two children, for 0 and 1 value of bit.
2) Initialize pre_xor = 0 and insert into the Trie.
3) Initialize result = minus infinite
4) Traverse the given array and do following for every
array element arr[i].
a) pre_xor = pre_xor ^ arr[i]
pre_xor now contains xor of elements from
arr[0] to arr[i].
b) Query the maximum xor value ending with arr[i]
from Trie.
c) Update result if the value obtained in step
4.b is more than current value of result.
4.b如何工作?
我们可以从上述算法中观察到,我们构建了一个Trie,其中包含给定数组的所有前缀的XOR。为了找到以arr [i]结尾的最大XOR子数组,可能有两种情况。
i)前缀本身具有以arr [i]结尾的最大XOR值。例如,如果{8,2,1,12}中的i = 2,则以arr [2]结尾的最大子数组xor为整个前缀。
ii)我们需要删除一些前缀(从0到i-1的索引结束)。例如,如果{8,2,1,12}中的i = 3,则以arr [3]结尾的最大子数组xor以arr [1]开头,我们需要删除arr [0]。
为了找到要删除的前缀,我们在Trie中找到与当前前缀具有最大XOR值的条目。如果我们用当前前缀对先前的前缀进行XOR,我们将得到以arr [i]结尾的最大XOR值。
如果没有要删除的前缀(情况i),则返回0(这就是为什么在Trie中插入0)。
下面是上述想法的实现:
C++
// C++ program for a Trie based O(n) solution to find max
// subarray XOR
#include
using namespace std;
// Assumed int size
#define INT_SIZE 32
// A Trie Node
struct TrieNode
{
int value; // Only used in leaf nodes
TrieNode *arr[2];
};
// Utility function to create a Trie node
TrieNode *newNode()
{
TrieNode *temp = new TrieNode;
temp->value = 0;
temp->arr[0] = temp->arr[1] = NULL;
return temp;
}
// Inserts pre_xor to trie with given root
void insert(TrieNode *root, int pre_xor)
{
TrieNode *temp = root;
// Start from the msb, insert all bits of
// pre_xor into Trie
for (int i=INT_SIZE-1; i>=0; i--)
{
// Find current bit in given prefix
bool val = pre_xor & (1<arr[val] == NULL)
temp->arr[val] = newNode();
temp = temp->arr[val];
}
// Store value at leaf node
temp->value = pre_xor;
}
// Finds the maximum XOR ending with last number in
// prefix XOR 'pre_xor' and returns the XOR of this maximum
// with pre_xor which is maximum XOR ending with last element
// of pre_xor.
int query(TrieNode *root, int pre_xor)
{
TrieNode *temp = root;
for (int i=INT_SIZE-1; i>=0; i--)
{
// Find current bit in given prefix
bool val = pre_xor & (1<arr[1-val]!=NULL)
temp = temp->arr[1-val];
// If there is no prefix with opposite
// bit, then look for same bit.
else if (temp->arr[val] != NULL)
temp = temp->arr[val];
}
return pre_xor^(temp->value);
}
// Returns maximum XOR value of a subarray in arr[0..n-1]
int maxSubarrayXOR(int arr[], int n)
{
// Create a Trie and insert 0 into it
TrieNode *root = newNode();
insert(root, 0);
// Initialize answer and xor of current prefix
int result = INT_MIN, pre_xor =0;
// Traverse all input array element
for (int i=0; i
Java
// Java program for a Trie based O(n) solution to
// find max subarray XOR
class GFG
{
// Assumed int size
static final int INT_SIZE = 32;
// A Trie Node
static class TrieNode
{
int value; // Only used in leaf nodes
TrieNode[] arr = new TrieNode[2];
public TrieNode() {
value = 0;
arr[0] = null;
arr[1] = null;
}
}
static TrieNode root;
// Inserts pre_xor to trie with given root
static void insert(int pre_xor)
{
TrieNode temp = root;
// Start from the msb, insert all bits of
// pre_xor into Trie
for (int i=INT_SIZE-1; i>=0; i--)
{
// Find current bit in given prefix
int val = (pre_xor & (1<=1 ? 1 : 0;
// Create a new node if needed
if (temp.arr[val] == null)
temp.arr[val] = new TrieNode();
temp = temp.arr[val];
}
// Store value at leaf node
temp.value = pre_xor;
}
// Finds the maximum XOR ending with last number in
// prefix XOR 'pre_xor' and returns the XOR of this
// maximum with pre_xor which is maximum XOR ending
// with last element of pre_xor.
static int query(int pre_xor)
{
TrieNode temp = root;
for (int i=INT_SIZE-1; i>=0; i--)
{
// Find current bit in given prefix
int val = (pre_xor & (1<= 1 ? 1 : 0;
// Traverse Trie, first look for a
// prefix that has opposite bit
if (temp.arr[1-val] != null)
temp = temp.arr[1-val];
// If there is no prefix with opposite
// bit, then look for same bit.
else if (temp.arr[val] != null)
temp = temp.arr[val];
}
return pre_xor^(temp.value);
}
// Returns maximum XOR value of a subarray in
// arr[0..n-1]
static int maxSubarrayXOR(int arr[], int n)
{
// Create a Trie and insert 0 into it
root = new TrieNode();
insert(0);
// Initialize answer and xor of current prefix
int result = Integer.MIN_VALUE;
int pre_xor =0;
// Traverse all input array element
for (int i=0; i
Python3
"""Python implementation for a Trie based solution
to find max subArray XOR"""
"""structure of Trie Node"""
class Node:
def __init__(self, data):
self.data = data
self.left = None # left node for 0
self.right = None # right node for 1
""" class for implementing Trie """
class Trie:
def __init__(self):
self.root = Node(0)
"""insert pre_xor to trie with given root"""
def insert(self, pre_xor):
self.temp = self.root
"""start from msb, insert all bits of pre_xor
into the Trie"""
for i in range(31, -1, -1):
"""Find current bit in prefix sum"""
val = pre_xor & (1<
C#
using System;
// C# program for a Trie based O(n) solution to
// find max subarray XOR
public class GFG
{
// Assumed int size
public const int INT_SIZE = 32;
// A Trie Node
public class TrieNode
{
public int value; // Only used in leaf nodes
public TrieNode[] arr = new TrieNode[2];
public TrieNode()
{
value = 0;
arr[0] = null;
arr[1] = null;
}
}
public static TrieNode root;
// Inserts pre_xor to trie with given root
public static void insert(int pre_xor)
{
TrieNode temp = root;
// Start from the msb, insert all bits of
// pre_xor into Trie
for (int i = INT_SIZE-1; i >= 0; i--)
{
// Find current bit in given prefix
int val = (pre_xor & (1 << i)) >= 1 ? 1 : 0;
// Create a new node if needed
if (temp.arr[val] == null)
{
temp.arr[val] = new TrieNode();
}
temp = temp.arr[val];
}
// Store value at leaf node
temp.value = pre_xor;
}
// Finds the maximum XOR ending with last number in
// prefix XOR 'pre_xor' and returns the XOR of this
// maximum with pre_xor which is maximum XOR ending
// with last element of pre_xor.
public static int query(int pre_xor)
{
TrieNode temp = root;
for (int i = INT_SIZE-1; i >= 0; i--)
{
// Find current bit in given prefix
int val = (pre_xor & (1 << i)) >= 1 ? 1 : 0;
// Traverse Trie, first look for a
// prefix that has opposite bit
if (temp.arr[1 - val] != null)
{
temp = temp.arr[1 - val];
}
// If there is no prefix with opposite
// bit, then look for same bit.
else if (temp.arr[val] != null)
{
temp = temp.arr[val];
}
}
return pre_xor ^ (temp.value);
}
// Returns maximum XOR value of a subarray in
// arr[0..n-1]
public static int maxSubarrayXOR(int[] arr, int n)
{
// Create a Trie and insert 0 into it
root = new TrieNode();
insert(0);
// Initialize answer and xor of current prefix
int result = int.MinValue;
int pre_xor = 0;
// Traverse all input array element
for (int i = 0; i < n; i++)
{
// update current prefix xor and insert it
// into Trie
pre_xor = pre_xor ^ arr[i];
insert(pre_xor);
// Query for current prefix xor in Trie and
// update result if required
result = Math.Max(result, query(pre_xor));
}
return result;
}
// Driver program to test above functions
public static void Main(string[] args)
{
int[] arr = new int[] {8, 1, 2, 12};
int n = arr.Length;
Console.WriteLine("Max subarray XOR is " + maxSubarrayXOR(arr, n));
}
}
// This code is contributed by Shrikant13
输出:
Max subarray XOR is 15