力扣(leetcode) 1310. 子数组异或查询 (前缀异或和解法)、(暴力解法)

题目是这样的:
有一个正整数数组 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了。
--------------一个渣渣小白的刷题日记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深度不学习!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值