找到数组中出现过一次的数

今天在学刷力扣的题的时候遇到一个很有意思的题目:

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

刚开始拿到这个题的时候,我的想法其实暴力破解,还是想要用利用一个时间复杂度较好的排序算法先排序,然后在进行遍历查找那一个元素,但是显然,在一般情况下的排序算法最好的时间复杂度也是nlogn,所以我就陷入困惑。。。

但是在看了大神的代码后,突然回忆起来曾经学过的位运算,也许能解决这道题目。

首先抬出与本题相关的位运算的基本公式:

  1. 任何数与自身进行异或运算,等于0。如1 ^ 1 = 0,5 ^ 5 = 0(101 ^ 101 = 0)
  2. 任何数与0进行异或运算,等于其本身。如0 ^ 1 = 1,5 ^ 0 = 5,(101^000 = 101)
  3. 异或运算具有交换律:a ^ b ^ c = a ^ c ^ b,如5 ^1 ^5 = 5 ^ 5 ^ 1 = 0 ^ 1 = 1)

有了上述的公式可以很好地得到最后只出现一次的元素,具体做法如下。

  1. 第一步首先用0与数组的第一个数字异或运算,得到本身(这一步其实也是为了使循环里的操作都是一样的)
  2. 每次循环都使当前数组的值与之前的值进行异或
  3. 重复第二步,直至数组元素结束
  4. 根据交换律可以得到最后只出现的一次的值

例如:{1,3,3,1,6,6,5}(为了方便看懂,我把十进制数字转换为对应的二进制)

第一步: 000 ^ 001 = 001
第二步: 001 ^ 011 = 010
第三步: 010 ^ 011 = 001
第四步: 001 ^ 001 = 000
第五步: 000 ^ 110 = 110
第六步: 110 ^ 110 = 000
第七步: 000 ^ 101 = 101

所以最后的答案就是101!

最后附上我使用C语言的代码!

int singleNumber(int* nums, int numsSize){
    int i;
    int k = 0;
    for(i = 0;i<numsSize;i++)
    {
        k = k^nums[i];
    }
    return k;
}

也算是今天学习的感悟,才开始刷题,感觉很有意思!希望以后也能多多收获知识!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值