(leetcode)1310. 子数组异或查询 -2021/5/12

本文介绍了一种解决子数组异或查询问题的有效方法。通过使用滑动窗口技术,优化了原始的暴力求解策略,显著提高了算法效率。

1310. 子数组异或查询 javascript

题目
有一个正整数数组 arr,现给你一个对应的查询数组 queries,其中 queries[i] = [Li, Ri]。

对于每个查询 i,请你计算从 Li 到 Ri 的 XOR 值(即 arr[Li] xor arr[Li+1] xor … xor arr[Ri])作为本次查询的结果。

并返回一个包含给定查询 queries 所有结果的数组。

example:

输入: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

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

思路1 javascript

  • 我用的暴力直接接法,先获取到queries数组中的对应下标,找到对应的元素,然后去arr中获取到再进行异或,最后都放入到返回数组中。

代码1

var xorQueries = function(arr, queries) {
    var result_arr = [];
    for(var i=0;i<queries.length;i++){
        var start = queries[i][0];
        var end = queries[i][1];
        // console.log(arr[start])
        var new_arr = arr.slice(start,end+1)
        //console.log('new_arr',new_arr)
        var result = 0;
        for(var j=0;j<new_arr.length;j++){
            //console.log(' ',new_arr[j])
            result ^= new_arr[j]
        }
        result_arr.push(result)
    }
    return result_arr
};

在这里插入图片描述
但是用了1840ms,因此就开始想优化办法了。

思路2 javascript【来源于大佬的思路】

  • 使用滑动窗口
    在这里插入图片描述
  • 先复制原始queries数组,对其进行坐标排序,以保证在不破坏原始数组的情况下对其进行操作
    -复制数组 主要是因为,返回的结果数组要按照原始数组的顺序返回
  • 然后利用滑动窗口进行滑动计算。排序的目的是防止每次滑动的幅度小一点。

代码2

var xorQueries = function(arr, queries) {
    const ret = new Uint32Array(queries.length);
    const map = new Map();
    // 复制原始数组,并按照左边界从小到大排序,如果左边界相同,再按照右边界从小到大排序
    // 使得所有的操作都在拷贝数组上进行,这样的可以保证最后的输出顺序与原始queries顺序相同
    const sorted = [...queries].sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
    let val = left = right = 0;
    for (let i = 0; i < sorted.length; ++i) {
        const start = sorted[i][0];
        const end = sorted[i][1];
        // 移动左边界
        while (left < start) val ^= arr[left++];
        // 移动右边界,需要区分两种情况,因为是基于左边界排序的,所以新的右边界可能比之前的右边界小
        while (right <= end) val ^= arr[right++];
        while (right > end + 1) val ^= arr[--right];

        map.set(left + '-' + (right - 1), val);
    }
    // 根据得到的map映射,去原始queries数组中获取到数据
    for (let i = 0; i < queries.length; ++i) {
        ret[i] = map.get(queries[i][0] + '-' + queries[i][1]);
    }
    return ret;
};

在这里插入图片描述

时间缩短了很多

学艺不精,还需努力💪

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值