题目是这样的:
有一个正整数数组 arr,现给你一个对应的查询数组 queries,其中 queries[i] = [Li, Ri]。
对于每个查询 i,请你计算从 Li 到 Ri 的 XOR 值(即 arr[Li] xor arr[Li+1] xor … xor arr[Ri])作为本次查询的结果。
并返回一个包含给定查询 queries 所有结果的数组。
我不知道有没有小伙伴和我一样没有看懂题。。可能是大半夜的缘故 脑子不转了哈哈。。
随即去看了一下题目给的实例 就很好理解了。
实例:
输入:arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]]
输出:[2,7,14,8]
查询的 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数组和queries数组是已经给你的。只需要看queries里的一维数组的值去算arr对应下标的异或和就行了 。
比如【0,1】 , 就是指arr数组里下标从0到1的数字的异或 即1 xor 3。
到这应该大家都明白题意了,先说一个比较好理解的普通方法。暴力解~~~
必备知识:
1.任何数和0异或都等于他本身 比如 3 ^ 0 = 3
2.任何数和他自己异或都等于0 比如 4 ^ 4 = 0
// An highlighted block
arr = [1,3,4,8]
queries = [[0,1],[1,2],[0,3],[3,3]]
result = []
for i in queries:
if i[0] == i[1]: # 排除两数相等的情况 像【1,1】这种
result.append(arr[i[0]])
else:
j = 0
num = arr[j + i[0]]
while True: # 开始无脑暴力解
if abs(i[1] - i[0]) >= j + 1 : # abs就是结果为负的话把他变正
# 这里加abs其实有点多余 因为仔细读题可发现 queries里的一维数组必定是前面的数大于后面的,
j += 1
num = num ^ arr[j + i[0]]
else:
result.append(num)
break
print(result)
上面这一段代码在leetcode里提交 42个测试用了跑通了40个 然后超时了哈哈。。。
看评论区学习,使用前缀和来解这道题~~~
关于前缀和的解释:
假设我们有数组 arr: [1,2,3,4,5];
前零项和的值为: 0 = 0
前一项和的值为: 1 = 1
前二项和的值为: 1+2 = 3
前三项和的值为: 1+2+3 = 6
前四项和的值为: 1+2+3+4 = 10
前五项和的值为: 1+2+3+4+5 = 15
因此它的前缀和数组为 preSum: [0, 1, 3, 6, 10, 15];
tip: (1 ^ 2) ^(1 ^ 2 ^ 3 ^ 4) = 3 ^ 4
本题将 加号换成异或理解即可
Python:
// An highlighted block
arr = [1,3,4,8]
queries = [[0,1],[1,2],[0,3],[3,3]]
pre = []
temp = 0
for i in arr:
temp = temp ^ i
# temp第一项为0 所以他和i异或就是i(前1项异或和 等于 他自己)
# 这里每次只需要和前面的一项异或即可 因为前面的一项就是前面全部的异或和
# 比如~现有前缀异或数组=【1,4,5】 这里的1就是arr前一项的异或和
# 第二项4就是arr数组前两项的异或和(1 ^ 3)
# 当求第三项5的时候 只需要用arr数组的第三项和第前面算出来的(4)异或
# 也就是5^4 而4是又(1^3)计算而得
pre.append(temp)
print(pre) # 此时得到前缀异或数组pre
ans = [] # 空数组存结果
for l, r in queries:
# pre=[1, 2, 6, 14] l=0 r=3 1 ^ 14 ^ 1 [0,3]
# pre=[1, 2, 6, 14] l=1 r=2 2 ^ 6 ^ 3 [1,2]
ans.append(pre[l] ^ pre[r] ^ arr[l])
# 这里用到了和自身异或为0的知识点
# 用【0,3】来举例 题中要求queries[0,3] 从第一项到第四项的异或和
# pre[l] ^ pre[r] l=0 r=3 即 pre[0] ^ pre[3]
# 也就是前缀数组的第一项和第四项 arr数组的 第一项 ^ 前四项的异或 = 二三四项的异或和
# 所以需要再异或一下第一项 就是arr[l]
print(ans)
再次提交
C语言:
无聊那vim写了个c的
#include<stdio.h>
#include<string.h>
int main()
{
int i = 0;
int arr[4] ={1,3,4,8};
int queries[2][4] ={{0,1},{1,2},{0,3},{3,3}};
i = sizeof(arr)/sizeof(arr[0]); // i存了arr数组长度
int res = 0;
int pre[4] = {};
int temp = 0;
int result[4] = {};
for(int j=0;j<4;j++)
{
temp = temp ^ arr[j];
pre[j] = temp;
}
// 这时候的pre已经存储了前缀和
for(int q=0;q<4;q++)
for(int w=0;w<1;w++)
{
res = pre[queries[q][w]]^pre[queries[q][w+1]]^arr[queries[q][w]];
result[q] = res;
}
for(int k=0;k<4;k++)
{
printf("%d",result[k]);
}
return 0;
}
这段代码没测试 不一定对可以做个借鉴
机子里没有ide 用vim写的我头疼
大学那会光用C写题 忘了不少 现在都pycharm哈哈 。可能以后刷力扣就用py3了不会再写C了。
--------------一个渣渣小白的刷题日记