📌  相关文章
📜  子数组的异或(元素范围)

📅  最后修改于: 2022-05-13 01:57:05.315000             🧑  作者: Mango

子数组的异或(元素范围)

给定一个包含 n 个整数的数组 arr[] 和一些查询。每个查询的形式为 (L, R),其中 L 和 R 是数组的索引。求子数组arr[L…R]的异或值,即[L,R]范围内的所有元素异或得到的值。假设基于 0 的索引并且每个数组元素是一个 32 位无符号整数。
例子:

Input : arr[] = {2, 5, 1, 6, 1, 2, 5}
        L =  1, R = 4
Output : 3
The XOR value of arr[1...4] is 3.

Input : arr[] = {2, 5, 1, 6, 1, 2, 5}
        L = 0, R = 6
Output : 6
The XOR value of arr[0...6] is 6.

方法:
一个简单的解决方案是对每个查询从索引 L 到索引 R 遍历给定数组。这导致处理每个查询的时间复杂度为 O(n)。如果有 q 个查询,则所需的总时间将为 O(q*n)。对于大量查询和大型数组,此解决方案不是最佳的。
一个有效的解决方案是首先对数组进行预处理。有两个观察会有所帮助:

  1. 问题陈述中提到每个数组元素都是一个 32 位无符号数。因此,结果也将是一个 32 位无符号数。
  2. 当多个位异或时,如果有奇数个 1,则结果为 1,否则结果为 0。

使用观察 1,创建一个大小为 32*n 的二维数组 cnt。该数组将用于存储 1 的计数。元素cnt[i][j] 表示第i 位到索引j 的1 的计数,即在第i 位位置的子数组arr[0..j] 中存在多少个1。
根据观察 2 获得 XOR 值,需要找到子数组 arr[L…R] 中所有 32 位位置的 1 的个数。这可以在cnt数组的帮助下完成。子数组 arr[L…R] 中第 i 个位的个数为 cnt[i][R] – cnt[i][L-1]。如果第 i 位 1 的个数是奇数,则结果中将设置第 i 位。如果设置了第 i 位,则可以通过添加对应于第 i 位的 2 的幂来获得结果。
根据该算法处理每个查询将花费 O(32) 即恒定时间。创建 cnt 数组的预处理阶段将花费 O(n) 时间。因此,该解决方案对于 q 个查询的总时间复杂度为 O(n+q)。
执行:

C++
#include 
using namespace std;
 
// Function to preprocess the array and find count of
// number of ones upto jth index for ith bit.
void preprocess(int arr[], int n, vector >& cnt)
{
    int i, j;
 
    // Run a loop for each bit position from
    // 0 to 32.
    for (i = 0; i < 32; i++) {
        cnt[i][0] = 0;
        for (j = 0; j < n; j++) {
            if (j > 0) {
 
                // store previous count of 1s
                // for ith bit position.
                cnt[i][j] = cnt[i][j - 1];
            }
 
            // Check if ith bit for jth element
            // of array is set or not. If it is
            // set then increase count of 1 for
            // ith bit by 1.
            if (arr[j] & (1 << i))
                cnt[i][j]++;
        }
    }
}
 
// Function to find XOR value for a range of array elements.
int findXOR(int L, int R, const vector > cnt)
{
 
    // variable to store final answer.
    int ans = 0;
 
    // variable to store number of 1s for ith bit
    // in the range L to R.
    int noOfOnes;
 
    int i, j;
 
    // Find number of 1s for each bit position from 0
    // to 32.
    for (i = 0; i < 32; i++) {
        noOfOnes = cnt[i][R] - ((L > 0) ? cnt[i][L - 1] : 0);
 
        // If number of 1s are odd then in the result
        // ith bit will be set, i.e., 2^i will be present in
        // the result. Add 2^i in ans variable.
        if (noOfOnes & 1) {
            ans += (1 << i);
        }
    }
 
    return ans;
}
 
int main()
{
    int arr[] = { 2, 5, 1, 6, 1, 2, 5 };
    int n = sizeof(arr) / sizeof(arr[0]);
    vector > cnt(32, vector(n));
    preprocess(arr, n, cnt);
    int L = 1;
    int R = 4;
    cout << findXOR(L, R, cnt);
    return 0;
}


Java
class GFG
{
 
    // Function to preprocess the array and find count of
    // number of ones upto jth index for ith bit.
    static void preprocess(int arr[], int n, int[][] cnt)
    {
        int i, j;
 
        // Run a loop for each bit position from
        // 0 to 32.
        for (i = 0; i < 32; i++)
        {
            cnt[i][0] = 0;
            for (j = 0; j < n; j++)
            {
                if (j > 0)
                {
 
                    // store previous count of 1s
                    // for ith bit position.
                    cnt[i][j] = cnt[i][j - 1];
                }
 
                // Check if ith bit for jth element
                // of array is set or not. If it is
                // set then increase count of 1 for
                // ith bit by 1.
                if ((arr[j] & (1 << i)) >= 1)
                    cnt[i][j]++;
            }
        }
    }
 
    // Function to find XOR value for a range of array elements.
    static int findXOR(int L, int R, int[][] cnt)
    {
 
        // variable to store final answer.
        int ans = 0;
 
        // variable to store number of 1s for ith bit
        // in the range L to R.
        int noOfOnes;
 
        int i, j;
 
        // Find number of 1s for each bit position from 0
        // to 32.
        for (i = 0; i < 32; i++)
        {
            noOfOnes = cnt[i][R] - ((L > 0) ? cnt[i][L - 1] : 0);
 
            // If number of 1s are odd then in the result
            // ith bit will be set, i.e., 2^i will be present in
            // the result. Add 2^i in ans variable.
            if (noOfOnes % 2 == 1)
            {
                ans += (1 << i);
            }
        }
 
        return ans;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int arr[] = { 2, 5, 1, 6, 1, 2, 5 };
        int n = arr.length;
        int[][] cnt = new int[32][n];
        preprocess(arr, n, cnt);
        int L = 1;
        int R = 4;
        System.out.print(findXOR(L, R, cnt));
    }
}
 
// This code is contributed by Rajput-Ji


Python3
# Function to preprocess the array and
# find count of number of ones upto
# jth index for ith bit.
def preprocess(arr, n, cnt):
 
    # Run a loop for each bit position
    # from 0 to 32.
    for i in range(32):
        cnt[i][0] = 0
        for j in range(n):
            if (j > 0):
 
                # store previous count of 1s
                # for ith bit position.
                cnt[i][j] = cnt[i][j - 1]
 
            # Check if ith bit for jth element
            # of array is set or not. If it is
            # set then increase count of 1 for
            # ith bit by 1.
            if (arr[j] & (1 << i)):
                cnt[i][j] += 1
 
# Function to find XOR value
# for a range of array elements.
def findXOR(L, R, cnt):
 
    # variable to store final answer.
    ans = 0
 
    # variable to store number of 1s
    # for ith bit in the range L to R.
    noOfOnes = 0
 
    # Find number of 1s for each
    # bit position from 0 to 32.
    for i in range(32):
        if L > 0:
            noOfOnes = cnt[i][R] - cnt[i][L - 1]
        else:
            noOfOnes = cnt[i][R]
 
        # If number of 1s are odd then in the result
        # ith bit will be set, i.e., 2^i will be
        # present in the result. Add 2^i in ans variable.
        if (noOfOnes & 1):
            ans += (1 << i)
 
    return ans
 
# Driver Code
arr = [2, 5, 1, 6, 1, 2, 5]
 
n = len(arr)
 
cnt = [[0 for i in range(n)]
          for i in range(32)]
 
preprocess(arr, n, cnt)
 
L = 1
R = 4
print(findXOR(L, R, cnt))
 
# This code is contributed by Mohit Kumar


C#
using System;
 
class GFG
{
 
    // Function to preprocess the array and find count of
    // number of ones upto jth index for ith bit.
    static void preprocess(int []arr, int n, int[,] cnt)
    {
        int i, j;
 
        // Run a loop for each bit position from
        // 0 to 32.
        for (i = 0; i < 32; i++)
        {
            cnt[i, 0] = 0;
            for (j = 0; j < n; j++)
            {
                if (j > 0)
                {
 
                    // store previous count of 1s
                    // for ith bit position.
                    cnt[i, j] = cnt[i, j - 1];
                }
 
                // Check if ith bit for jth element
                // of array is set or not. If it is
                // set then increase count of 1 for
                // ith bit by 1.
                if ((arr[j] & (1 << i)) >= 1)
                    cnt[i, j]++;
            }
        }
    }
 
    // Function to find XOR value for a range of array elements.
    static int findXOR(int L, int R, int[,] cnt)
    {
 
        // variable to store readonly answer.
        int ans = 0;
 
        // variable to store number of 1s for ith bit
        // in the range L to R.
        int noOfOnes;
 
        int i;
 
        // Find number of 1s for each bit position from 0
        // to 32.
        for (i = 0; i < 32; i++)
        {
            noOfOnes = cnt[i, R] - ((L > 0) ? cnt[i, L - 1] : 0);
 
            // If number of 1s are odd then in the result
            // ith bit will be set, i.e., 2^i will be present in
            // the result. Add 2^i in ans variable.
            if (noOfOnes % 2 == 1)
            {
                ans += (1 << i);
            }
        }
 
        return ans;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        int []arr = { 2, 5, 1, 6, 1, 2, 5 };
        int n = arr.Length;
        int[,] cnt = new int[32, n];
        preprocess(arr, n, cnt);
        int L = 1;
        int R = 4;
        Console.Write(findXOR(L, R, cnt));
    }
}
 
// This code is contributed by Rajput-Ji


Javascript


输出:
3

时间复杂度: O(n+q)
辅助空间: O(n)