📜  在给定数组中找到最大子数组XOR

📅  最后修改于: 2021-04-29 18:57:04             🧑  作者: Mango

给定一个整数数组。在给定数组中找到最大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