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;
};
时间缩短了很多
学艺不精,还需努力💪