位运算 Tips

位运算的异或 “^” 运算符

0. 异或原理

  • 0 ^ N = N;
  • N ^ N = 0;
  • 满足交换律 和 结合律。

1. 交换两个数的值

  • 假设需要交换两个数 a,b 的值:
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
  • 思路演示:
    为了方便演示不同的 a,b 分别定义新变量。
    • a_1 = a ^ b;
    • b_1 = a_1 ^ b = a ^ b ^ b = a;
    • a_2 = a_1 ^ b_1 = a ^ b ^ a = b;

2. 求解数组内奇数次的唯一数

  • 假设数组 arr 内有唯一的一个数出现了奇数次,其他数出现偶数次,求解这个唯一数:
    int eor = 0;
    for(int i; i < arr.length(); i++)
    {
        eor ^= arr[i];
    }
    System.out.println(eor);

3. 求解某数的二进制位的最右是 1 的位置

  • 数与自身取反加 1 进行与运算。
    int i = eor & (~eor + 1);

3.1 求解数组内奇数次的唯一的两个数

  • 假设数组 arr 内有唯一的两个数出现了奇数次,其他数出现偶数次,求解这两个唯一数。
  • 思路与求一个一样,但是求出的是两个唯一数的异或,需要在进行拆分:
    • 而两个数不一样代表着异或运算不为0,则这两个数至少有一位是不一样的,即运算结果至少保存一个位置的 1。
    • 此时可以使用求解最右的 1 位置,利用这个结果与数组内元素进行 与运算,将结果为 0(或1)的元素保留下来,与 0 进行异或运算,最后剩下的为其中的一个数;
    • 在利用这个数和两数的异或进行异或运算,的到另一个数。
    int eor = 0;
    for(int i; i < arr.length(); i++)
    {
        eor ^= arr[i]; // 两数的异或
    }
    int i = eor & (~eor + 1);  // 求两数不同的最右的 1 位置
    int ~eor = 0;
    for(int i; i < arr.length(); i++)
    {
        if(i & arr[i] == 0){
            ~eor ^= arr[i]; // 两数的其中一个
        }
    }
    System.out.println(~eor + " " + (eor ^ ~eor));  // 输出两个数
posted @   bok_tech  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
  1. 1 翻云覆雨 BLL
  2. 2 与我无关 阿冗
  3. 3 想去海边 夏日入侵企划
  4. 4 没有理想的人不伤心 新裤子
  5. 5 生活因你而火热 新裤子
没有理想的人不伤心 - 新裤子
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.
点击右上角即可分享
微信分享提示