每日一题——只出现一次的数字(III)

只出现一次的数字——III

题目链接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1wrPBgDu-1690767837684)(C:\Users\HUASHUO\AppData\Roaming\Typora\typora-user-images\image-20230731083138887.png)]

注:本题的解法建立在位运算——异或和题目《只出现一次的数字——I》之上,如果对这些内容不太熟悉,建议先看看:

位运算详解

只出现一次的数字——I


思路

我们先来回顾一下异或的特性:

异或是支持交换律的:a ^ b ^ c = b ^ a ^ c

a ^ a = 0相同的数异或为0

0 ^ a = a一个数和0异或得到的还是本身

a ^ b != 0 (a != b)(不等的数据异或的结果绝对不等于0)

对于这一题,我们先举一个具体的例子[1,2,3,4,5,1,2,3,4,6],该数组中除了5,6只出现了一次,其余元素都出现了两次。

我们不妨先将所有的元素异或到一起,得到的结果为:5 ^ 6,这时有小伙伴就要问了,这是两个数字的异或呀,怎么能将这两个数字分开,得到最后的结果呢?因此,我们可以将这个数组分成两组,并确保相同的数字在一组,只出现一次的两个数字不在同一组,这样,我们分别异或两个数组的数据,最后得到的不就是两个只出现一次的数据吗?

那么问题又来了,我们怎么确保分组时相同的元素在一组,只出现一次的两个元素不在一组呢?

就拿上面的例子来说,所有数字异或到一起后结果为5 ^ 6,这个结果不为0,那么就说明这个结果的二进制位一定有一位不为0(即一定有一位为1),而异或的计算规则是相异为1,因此我们就可以根据这这一位的不同来区分这两个数据


实现代码

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* singleNumber(int* nums, int numsSize, int* returnSize){
    *returnSize = 2;
    int* ret = (int*)malloc(sizeof(int) * 2);	//申请返回数组的内存
    memset(ret, 0, 8);	//将数组初始化为0

    //先将原数组的所有数据异或,得到结果
    int temp = 0;
    for(int i = 0; i < numsSize; i++)
        temp ^= nums[i];
    
    //算出只出现一次的两个数据的第pos二进制位不同
    int pos = 0;
    for(int i = 0; i < 32; i++)
    {
        if(((temp >> i) & 1) != 0)
        {
            pos = i;
            break;
        }
    }

    //将数据分组,原数组的数据第pos位为1分成一组,为0分成一组
    //同时将这两组数分别异或,得到最后结果
    for(int i = 0; i < numsSize; i++)
    {
        if(((nums[i] >> pos) & 1) != 0)
            ret[0] ^= nums[i];
        else
            ret[1] ^= nums[i];
    }

    //返回结果
    return ret;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Forward♞

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

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

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

打赏作者

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

抵扣说明:

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

余额充值