2021-05-12力扣每日一题

1310 子数组异或查询

问题描述:

​ 有一个正整数数组 arr,现给你一个对应的查询数组 queries,其中 queries[i] = [Li, Ri]。对于每个查询 i,请你计算从 Li 到 Ri 的 XOR 值(即 arr[Li] xor arr[Li+1] xor … xor arr[Ri])作为本次查询的结果。并返回一个包含给定查询 queries 所有结果的数组。

示例1:

输入:arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]]
输出:[2,7,14,8] 
解释:
数组中元素的二进制表示形式是:
1 = 0001 
3 = 0011 
4 = 0100 
8 = 1000 
查询的 XOR 值为:
[0,1] = 1 xor 3 = 2 
[1,2] = 3 xor 4 = 7 
[0,3] = 1 xor 3 xor 4 xor 8 = 14 
[3,3] = 8

示例2:

输入:arr = [4,8,2,10], queries = [[2,3],[1,3],[0,0],[0,3]]
输出:[8,0,4,4]

思路:

​ 这个问题乍一看不难,毕竟常理来说遍历一趟就什么都解决了,但这里如果遍历的话,我们需要重复计算的内容太多了,所以这里需要对之前计算的东西做一个保存,才能在时间上保证可以通过。

​ 第一个思路是新建一个二维数组,保存从 i 到 j 的异或值,后面输出的时候直接使用即可,但是这里存在一个问题,就是我们需要new的这个数组实在是太大了,并且里面有将近一半的空间是没有用的,因为我们只需要 j 大于等于 i 的那一部分值,反映到矩阵中就是一个矩阵的上半部分。所以对空间产生了极大地浪费。

​ 初级实现的时候,时间没有爆炸,空间爆炸了。

Java代码:

/** 
* @Description: 力扣1310题题解
* @return: 返回结果
* @Author: Mr.Gao
* @Date: 2021/5/12 
*/
public int[] xorQueries(int[] arr, int[][] queries) {
    int n = arr.length;
    int[][] temp = new int[n][n];
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            if(i==j){
                temp[i][j] = arr[i];
            }else{
                temp[i][j] = temp[i][j-1]^arr[j];
            }
        }
    }
    int m = queries.length;
    int[] re = new int[m];
    for (int i = 0; i < m; i++) {
        re[i] = temp[queries[i][0]][queries[i][1]];
    }
    return re;
}

​ 空间爆炸之后,我们就思考初始化的数组让其变得简单点,我们其实没有必要将所有匹配的异或值全部计算出来,只需要计算两个边界的值即可。也就是我们计算0号位置到其余各号位置的异或值,和其余各号位置到n-1号位置的异或值,然后在根据异或计算的特性,我们就可以根据这两个值来计算出所有左右边界的异或值。

​ 根据之前异或计算的结论,a异或b = c,那么abc三者的任意两个的异或都等于第三个变量的值。根据这个结论。

  • 我们可以先将数组中所有元素一起异或的值保存下来
  • 接着再异或从0到左边界的值,再异或从右边界到n-1号的值,我们就得出了从左边界+1到右边界-1的异或值
  • 再异或一下左边界和右边界就可以得到从左边界到右边界的异或值。

这样节约了空间和时间。

Java代码:

/** 
* @Description: 力扣1310题题解2
* @return: 返回结果
* @Author: Mr.Gao
* @Date: 2021/5/12 
*/

public int[] xorQueries2(int[] arr, int[][] queries) {
    int n = arr.length;
    //temp【0】保存从0到j的所有异或值,temp【1】保存从j到n-1的所有异或值。
    int[][] temp = new int[2][n];
    //x保存arr中所有元素的异或值
    int x = arr[0];

    temp[0][0] = arr[0];
    for(int i=1;i<n;i++){
        temp[0][i] = temp[0][i-1]^arr[i];
        x^=arr[i];
    }

    temp[1][n-1] = arr[n-1];
    for(int i = n-2;i>=0;i--){
        temp[1][i] = temp[1][i+1]^arr[i];
    }

    int m = queries.length;
    int[] re = new int[m];
    for (int i = 0; i < m; i++) {
        re[i] = x^temp[0][queries[i][0]]^temp[1][queries[i][1]]^arr[queries[i][0]]^arr[queries[i][1]];
    }
    return re;
}
  • 码字不易,还望素质三连!
上一篇:2021-05-13


下一篇:【java】1310. 子数组异或查询---使用位运算符,快速解决问题!!!