当前位置: 首页 > article >正文

位运算 -- 力扣

1486. 数组异或操作

1486. 数组异或操作
根据题意,使用参数 nstart 生成一个数组,最后返回数组中所有元素按位异或(XOR)后得到的结果。

首先,异或运算的规则是,当同一位的二进制数不同时结果为 1,否则为 0,比如 101 ⊕ 111 = 010 101 \oplus 111 = 010 101111=010
它有以下相关的性质:

  1. x ⊕ x = 0 x \oplus x = 0 xx=0
  2. x ⊕ 0 = x x \oplus 0 = x x0=x
  3. x ⊕ y = y ⊕ x x \oplus y = y \oplus x xy=yx
  4. ( x ⊕ y ) ⊕ z = x ⊕ ( y ⊕ z ) (x \oplus y) \oplus z = x \oplus (y \oplus z) (xy)z=x(yz)
  5. x ⊕ y ⊕ y = x x \oplus y \oplus y = x xyy=x
  6. ∀ i ∈ Z \forall i \in Z iZ 4 i ⊕ ( 4 i + 1 ) ⊕ ( 4 i + 2 ) ⊕ ( 4 i + 5 ) = 0 4i \oplus (4i+1) \oplus (4i+2) \oplus (4i+5) = 0 4i(4i+1)(4i+2)(4i+5)=0
  7. 当一个奇数和一个偶数进行异或运算时,结果的最低位一定是 1,比如 2 和 3。

额外的,如果 x 是偶数, x ⊕ 1 = x + 1 x \oplus 1 = x+1 x1=x+1;如果 x 是奇数, x ⊕ 1 = x − 1 x \oplus 1 = x-1 x1=x1。比如 6 ⊕ 1 = 110 ⊕ 001 = 111 = 7 6 \oplus 1=110 \oplus 001=111=7 61=110001=111=7 5 ⊕ 1 = 101 ⊕ 001 = 100 = 4 5 \oplus1=101 \oplus 001=100=4 51=101001=100=4

在本题中,我们需要计算 s t a r t ⊕ ( s t a r t + 2 ) ⊕ ( s t a r t + 4 ) ⊕ ⋯ ⊕ ( s t a r t + 2 ( n − 1 ) ) (1) start \oplus (start+2) \oplus (start+4) \oplus ⋯ \oplus (start+2(n−1)) \tag{1} start(start+2)(start+4)(start+2(n1))(1)
观察公式可以知道,这些数的奇偶性相同,因此它们的二进制表示中的最低位要么均为 1,要么均为 0。
于是我们可以把参与运算的数的二进制位的最低位提取出来单独处理。当且仅当 start 为奇数,且 n 也为奇数时,结果的二进制位的最低位才为 1,因此最低位 e 为 e = 1 & n & start

当 n = 4 时,start = 2,nums=[2, 4, 6, 8],最低位 e 为 0;
当 n = 4 时,start = 1,nums=[1, 3, 5, 7],最低位 e 为 0,原因:两个奇数进行异或操作结果为 0,因此偶数个奇数的最低位为 0;
当 n = 3 时,start = 1,nums=[1, 3, 5],最低位 e 为 1,原因: 0 ⊕ 1 = 1 0 \oplus 1 = 1 01=1

此时我们可以将公式转化为 ( s ⊕ ( s + 1 ) ⊕ ( s + 2 ) ⊕ ⋯ ⊕ ( s + n − 1 ) ) × 2 + e (2) (s \oplus (s+1) \oplus (s+2) \oplus ⋯ \oplus (s+n−1))×2+e \tag{2} (s(s+1)(s+2)(s+n1))×2+e(2) 其中 s = ⌊ s t a r t 2 ⌋ s=⌊\frac{start}{2}⌋ s=2start e e e 表示运算结果的最低位。舍去最低位后的数列恰成为一串连续的整数。

首先,将所有参与异或的元素都删除最后一位,即为右移一位, s t a r t 2 ⊕ s t a r t + 2 2 ⊕ s t a r t + 4 2 ⊕ . . . ⊕ s t a r t + 2 ( n − 1 ) 2 = s t a r t 2 ⊕ ( s t a r t 2 + 1 ) ⊕ ( s t a r t 2 + 2 ) ⊕ ⋯ ⊕ ( s t a r t 2 + n − 1 ) \frac{start}{2} \oplus \frac{start+2}{2} \oplus \frac{start+4}{2} \oplus ... \oplus \frac{start+2(n−1)}{2} = \frac{start}{2} \oplus (\frac{start}{2}+1)\oplus (\frac{start}{2}+2) \oplus ⋯ \oplus (\frac{start}{2}+n−1) 2start2start+22start+4...2start+2(n1)=2start(2start+1)(2start+2)(2start+n1)
然后,用上面得到的结果乘于 2,相当于左移一位,再加上最后一位值 e,使用 s s s 代替 s t a r t 2 \frac{start}{2} 2start,因此公式(1) 变为: ( s ⊕ ( s + 1 ) ⊕ ( s + 2 ) ⊕ ⋯ ⊕ ( s + n − 1 ) ) × 2 + e (s \oplus (s+1) \oplus (s+2) \oplus ⋯ \oplus (s+n−1))×2+e (s(s+1)(s+2)(s+n1))×2+e

这样我们可以描述一个函数 s u m X o r ( x ) sumXor(x) sumXor(x),表示 0 ⊕ 1 ⊕ 2 ⊕ ⋯ ⊕ x 0 \oplus 1 \oplus 2 \oplus ⋯ \oplus x 012x。利用异或运算的性质 6,我们可以将计算该函数的复杂度降低到 O(1),因为以 4 i 4i 4i 为开头的连续四个整数异或的结果为 0,所以 s u m X o r ( x ) sumXor(x) sumXor(x) 可以被表示为:
在这里插入图片描述
化简后的形式:
在这里插入图片描述

当 x = 4k 时,元素有 [0, 1, 2, …, 4k],因为前面的 [0,1, 2, …, 4k-1] 的异或操作的结果为 0,最后只剩下元素 x=4k;
当 x = 4k+1 时,剩下的元素有 ( x − 1 ) ⊕ x (x−1) \oplus x (x1)x,根据上面性质7,这个化简后的结果为 1;
当 x = 4k+2 时,剩下的元素有 ( x − 2 ) ⊕ ( x − 1 ) ⊕ x = 1 ⊕ ( 4 k + 2 ) = x ⊕ 1 = x + 1 (x−2) \oplus (x−1) \oplus x = 1 \oplus (4k+2) = x \oplus 1 = x+1 (x2)(x1)x=1(4k+2)=x1=x+1,其中 x x x 是偶数;
当 x = 4k+3 时,剩下的元素有 ( x − 3 ) ⊕ ( x − 2 ) ⊕ ( x − 1 ) ⊕ x (x−3) \oplus (x−2) \oplus (x−1) \oplus x (x3)(x2)(x1)x,其中 ( x − 3 ) ⊕ ( x − 2 ) = ( x − 1 ) ⊕ x = 0 (x−3) \oplus (x−2) = (x−1) \oplus x = 0 (x3)(x2)=(x1)x=0,参考上面性质7。

“以 4 i 4i 4i 为开头的连续四个整数异或的结果为 0” :连续四个整数的异或结果为 0,即为 k ⊕ ( k + 1 ) ⊕ ( k + 2 ) ⊕ ( k + 3 ) = 0 k \oplus (k+1) \oplus (k+2) \oplus (k+3)=0 k(k+1)(k+2)(k+3)=0,所以以 4 的倍数为起点(即 k = 4 i k=4i k=4i)的四个连续整数的异或结果也为 0。这个性质使得我们在处理长度为 4 的一组数时,不需要逐一计算它们的异或结果,而是直接知道它们的异或为 0,将问题的规模大幅缩小。

根据公式 (2),我们需要计算出[s, s+1, …, s+n-1] 这个范围的异或结果,设这个结果为 x x x
显然 s u m X o r ( s − 1 ) ⊕ x = s u m X o r ( s + n − 1 ) sumXor(s-1) \oplus x = sumXor(s+n-1) sumXor(s1)x=sumXor(s+n1)。根据性质 3 和 5 可得出 x = s u m X o r ( s − 1 ) ⊕ s u m X o r ( s + n − 1 ) x = sumXor(s-1) \oplus sumXor(s+n-1) x=sumXor(s1)sumXor(s+n1),其中 s u m X o r ( s + n − 1 ) sumXor(s+n−1) sumXor(s+n1) 表示从 0 到 s+n−1 的所有元素的异或结果。

流程:
① 计算参与运算的数的二进制位的最低位的值 e;
② 计算 s = ⌊ s t a r t 2 ⌋ s=⌊\frac{start}{2}⌋ s=2start
③ 分别计算 s u m X o r ( s + n − 1 ) sumXor(s+n-1) sumXor(s+n1) s u m X o r ( s − 1 ) sumXor(s-1) sumXor(s1),再对这两个结果进行异或操作得到 ret;
④ 计算 ret * 2 + e 。

class Solution {
public:
    int xor_n(int n) {
        switch (n % 4) {
            case 0: return n;
            case 1: return 1;
            case 2: return n+1;
            default: return 0;
        }
    }
    int xorOperation(int n, int start) {
        int e = 1 & n & start, s = start / 2;
        int ret = xor_n(s-1) ^ xor_n(s + n - 1);
        return ret * 2 + e;
    }
};
var xorOperation = function(n, start) {
    const xor_n = (num) => {
        switch(num % 4) {  
            case 0: return num;   // 4k % 4 = 0
            case 1: return 1;
            case 2: return num+1;
            default: return 0;
        }
    }
    const e = 1 & n & start, s = start >> 1;  
    const ret = xor_n(s-1) ^ xor_n(s+n-1);
    return ret * 2 + e;
};

http://www.kler.cn/news/340458.html

相关文章:

  • Springboot 文件上传
  • 海洋鱼类图像分类分割系统源码&数据集分享
  • MySQL进阶 - 索引
  • SpringIoC容器的初识
  • 软件验证与确认实验二-单元测试
  • YOLO11改进 | 卷积模块 | 轻量化GSConv替换普通的conv
  • NLP: SBERT介绍及sentence-transformers库的使用
  • Spring Boot大学生就业招聘系统的开发策略
  • 基于SSM的家庭理财系统的设计与实现
  • 掌握 ASP.NET Web 开发:从基础到身份验证
  • 【Java 并发编程】解决多线程中数据错乱问题
  • 前端vue-安装pinia,它和vuex的区别
  • Vue中watch监听属性的一些应用总结
  • 微信小程序启动不起来,报错凡是以~/包名/*.js路径的文件,都找不到,试过网上一切方法,最终居然这么解决的,【避坑】命运的齿轮开始转动
  • 【Linux】man手册安装使用
  • 以一个B站必剪应用Bug过一下CVSS 4.0评分
  • TCP网络通信——多线程
  • 重学SpringBoot3-集成Redis(二)之注解驱动
  • 408算法题leetcode--第26天
  • Kubernetes--深入理解Pod资源管理