只出现一次的数字 ----<异或位运算>-----力扣

本文介绍了如何利用异或运算解决一道力扣的简单题目。异或运算遵循归零律、恒等律、交换律和结合律,使得在处理数组中出现一次的数字时变得简便。通过举例和代码展示,阐述了异或运算是如何找到数组中只出现一次的数字。此外,还提到了异或在不使用额外空间交换两个数的应用。
摘要由CSDN通过智能技术生成

异或位运算的妙用

在这里插入图片描述

这是一道力扣的简单题,最开始我想的是用数组,先对所有数据进行排序,然后遍历数组元素,如果a[i] = a[i+1],那么i+=2;continue;因为只有一个数字出现了一次,那么当a[i] != a[i+1]时,a[i]就是要找的数。

后面看了评论区之后,发现一种很简洁有意思的做法——按位异或


一、什么是异或?

之前离散数学里学习到这样一种特别的逻辑运算:按位异或。计算机进行按*异或运算的步骤为:

1、将两个数a、b先转换为二进制数此步就决定了后续异或运算中每一次对应位的异或运算都只有0或1参与

2、两个二进制数对应位进行异或运算,其规则是:如果参与异或运算的两个数相同,则该位的异或结果为0;否则,结果为1。

3、当所有位的异或运算都结束后,计算机再将得到的新二进制数转换为与a、b的进制相同的数输出,作为a^b的结果。

注:C语言里用符号“^”作为异或运算符,文章中的异或运算符也用这个表示

异或运算遵守的运算法则

  1. 归零律:a ^ a = 0
  2. 恒等律:a ^ 0 = a
  3. 交换律: a ^ b = b ^ a
  4. 结合律:a ^ b ^ c = (a ^ b) ^ c = a ^ (b ^ c)
  5. 自反:a ^ b ^ a = b (可使用交换律得到)

二、异或运算的实例以及一些说明

看再多理论方法,如果不去实战体验,那就相当于没学

1、先用一个简单例子表现一下上面所说的异或运算步骤

以十进制数 5 和 3 进行异或运算为例:

第一步:计算机将二者转换为二进制数

        5(十进制) -->  0101(二进制), 3(十进制)  -->  0011(二进制)

第二步:对应位进行异或运算
        0 1 0 1
        0 0 1 1
     ---------- (对应位进行异或运算,相同的数字异或,结果为0;不同的数字异或,结果为1)
  结果:0 1 1 0

        运算结果就是二进制数0110

第三步:将得到的二进制数转换为和参与运算的53一样的十进制数输出得到5异或3的结果
 
        5 ^ 3 = 6(C语言中用^表示异或运算符)

2、多个数据进行异或,当相同的数没挨在一起时,运算顺序

由于异或运算是满足交换律和结合律的,所以你大可认为在进行运算的时候,所有的数都会先进行交换,将相同的数放在一起,然后使用结合律先对相同的数进行异或运算,再进行后面的运算

举个例子:

   a ^ b ^ c ^ a ^ d ^ c ^ d
=a ^ a ^ b ^ d ^ d ^ c
=0 ^ b ^ 0 ^ c
=0 ^ 0 ^ b ^ c
=0 ^ b ^ c
然后再根据b、c的具体值进行之后的运算


三、题目的异或解法

有了以上对异或运算的理解后,就可以很容易使用异或的方法解决这道题了

代码如下

int singleNumber(int* nums, int numsSize)
{
    int b;
    b = nums[0];
    int i; b;
    for(i = 1; i < numsSize; i++)
    {
        b = b ^ nums[i];//相同的数之间异或为0,0异或a为a
    }
    return b;
}

四、异或的其他使用

1、不使用额外空间完成两个数的交换

借助异或在原来两个数的空间里直接对两个数进行修改,从而不必声明一个新的变量,来开辟一个新的空间做中转站,进而节省了内存

int a = 10, b = 5;

a = a ^ b;
b = a ^ b;
//上面这一步值得注意的是:这一步的a相当于10 ^ 5
//所以这一步的a ^ b实际上是:10 ^ 5 ^ 5
a = a ^ b;
//由上面第二步可知,b已经经过异或运算变成了10,所以这一步相当于:10 ^ 5 ^ 10

暂时记录到这里,以后有什么新的想法再写进来。如果有什么错误的地方,欢迎指出

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

六时二一

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

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

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

打赏作者

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

抵扣说明:

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

余额充值