按位异或的一处小妙用

按位异或操作符的一处妙用

1.按位异或的基础知识

我们都知道

  • a ^ a = 0
  • a ^ 0 = a
  • 同时按位异或操作符具有交换律 如:``a ^ b ^ c = a ^ c ^b`
  • 对于a ^ 其他数的结果是没有普遍规律的我们不需要掌握

2.按位异或的巧用一

用按位异或操作符我们可以不用创建一个变量就交换 a ,b 的值,

例:

a = a ^ b;
b = a ^ b;
a = a ^ b;

很多小伙伴看到这样的代码可能很疑惑,为什么这样就能交换两个数的值,其实这就要从a,b数值的二进制存储中说起

a的二进制形式是 101b的二进制形式为 110,因为 1 ^ 0 = 1, 0 ^ 0 = 0, 1 ^ 1 = 1。所以经过第一次的 a = a ^ b 的运算后,a的二进制形式变为了 011。那么继续经过第二次的运算后 b的二进制形式变为了 101 ,细心的同学肯定发现 b 的值变成了 a 的值,那么再进行最后一次的运算 ,因为这时 a = 011,b = 101,再进行最后一次的运算后 a 的值变为了 110。所以进行了两数的交换。这个方法对于任何两数的交换都能使用

3.按位异或的巧用二

我们继续来看一个题:

数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?

示例 1:

输入:[3,0,1]
输出:2

示例 2:

输入:[9,6,4,2,3,5,7,0,1]
输出:8

该题链接

  1. 首先我们假设该题是一个包含0到n有顺序的数组,但其中缺了一个

  2. 然后我们先在有顺序中进行探究

    首先要用到之前的知识

    A ^ A = 0
    A ^ 0 = A
    异或`具有交换律: `A^B^C = C^A^B
    
012346
012345

在这个表格中假设第一行代表数组中的元素

第二行代表其数组的下标

那么我们用0异或其数组中没一个元素和每一个元素的下标:

0 ^ 0 ^ 0 ^ 1 ^ 1 ^ 2 ^ 2 ^ 3 ^ 3 ^ 4 ^ 4 ^ 5 ^ 6 由交换律我们可以把一样的元素先进行异或操作 如 1 ^ 1 =0, 2 ^ 2 =0

所以上式最后得到 0 ^ 5 ^ 6,而又 0 ^ 任何数 = 任何数,所以最后剩下5和6,而5为上面数组中缺少的元素,而6为数组的长度

所以我们只需要对上式再异或数组的长度,最后的结果就是缺少的那个元素。

看到这里是不是觉得很巧妙啊

那对于乱序的数组又该怎么做呢?

还记得按位异或的交换律嘛,对了在乱序数组的运算中,我们只需运用交换律,就可把所有一样的元素再次像上面一样全部消除掉,最后只剩下缺少的元素了。

下面就是代码部分

int missingNumber(int* nums, int numsSize)  //nums是 数组的首地址(指针)   numsSize是数组大小
{
    int ret = 0;
    for(int i = 0;i<numsSize;i++)
    {
        ret = ret^i^nums[i];
    }
    return ret ^ numsSize; 
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值