LeetCode 260 只出现一次的数字(超详细)

LeetCode 260 只出现一次的数字

题目简述

给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按任意顺序返回答案。

进阶:你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?

思路讲解

   这道题其实是另一道题的进阶版本,如果此题问的是给定一个整数数组 nums,
   其中恰好有一个元素只出现一次,其余所有元素均出现两次。 
   找出只出现一次的那个元素,这个时候我们就可以将整个数组异或,得出来的就是那个数。
   而现在有两个只出现一次的数,那么我们整体异或出来的数就是这两个数异或的结果
   (如果有对异或不太了解的可以先去下面看一看,下面有介绍异或)。
   那么我们想做出这题,有两个思路,
   一个是将这两个数异或出来的结果分解出原来的两个数,而这种思路很难实现。
   而另一种思路是将这个题变成之前的那种只有一个出现一次的情况,
   将这两个数分别分出来,相当于把原来的这个数组分成两组,每组都只有这一个是只出现一次的,
   然后将这两组数据分别异或,这样就能分别出来这两个数。因为返回顺序是任意的,因此只要返回这两个数就行。

按代码片段分别讲解

//下面是思路的第一步,先将所有的数据都异或
    //先将所有的数据都异或
    int i = 0;
    int ret = 0;
    for (i = 0;i < numsSize;i++)
    {
        ret ^= nums[i];
    }
// 然后就是分组了,那么我们将异或完的数据的二进制的各个位与1异或找出哪一位是1
    //看异或的结果的哪一位是1
    int m = 0;
    while (((ret >> m) & 1) != 1)
    {
        m++;
    }
那么我们为什么要找出哪一位是1呢?
因为这两个数只出现一次,就代表着他们俩异或出来的结果肯定有一位是1
而我们找出这一位有什么作用呢?
按照我们的思路,我们需要将这两个数分别分到两组去,而除了这两个数之外的数字均出现了两次,
那么我们只需要根据这一位是1的和不是1的进行分组,
那么不光这两个出现一次的分到了不同的组里,每个组里的其他数字肯定也都是出现两次的。
 //将m位是1的都异或到一起
 //将m位是0的都异或到一起
    //将m位是1的都异或到一起
    //将m位是0的都异或到一起
    int x1 = 0;
    int x2 = 0;
    for (i = 0;i < numsSize;i++)
    {
        if ((nums[i] >> m) & 1)
        {
            x1 ^= nums[i];
        }
        else
        {
            x2 ^= nums[i];
        }

    }

完整解答

下面来看一下完整的解答
int* singleNumber(int* nums, int numsSize, int* returnSize)
{
    //先将所有的数据都异或
    int i = 0;
    int ret = 0;
    for (i = 0;i < numsSize;i++)
    {
        ret ^= nums[i];
    }
    //看异或的结果的哪一位是1
    int m = 0;
    while (((ret >> m) & 1) != 1)
    {
        m++;
    }

    //将m位是1的都异或到一起
    //将m位是0的都异或到一起
    int x1 = 0;
    int x2 = 0;
    for (i = 0;i < numsSize;i++)
    {
        if ((nums[i] >> m) & 1)
        {
            x1 ^= nums[i];
        }
        else
        {
            x2 ^= nums[i];
        }

    }
    int* RetArr = (int*)malloc(sizeof(int) * 2);
    RetArr[0] = x1;
    RetArr[1] = x2;
    *returnSize = 2;
    return RetArr;
}

如果还有哪里不清楚的可以给我留言。

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值