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

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

只出现一次的数字——III

题目链接

注:本题的解法建立在位运算——异或和题目《只出现一次的数字——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;
}
相关文章
【力扣每日一题】1365. 有多少小于当前数字的数字
【力扣每日一题】1365. 有多少小于当前数字的数字
|
5月前
|
存储 容器
【LeetCode刷题】只出现一次的数字(Ⅰ、Ⅱ、Ⅲ)
【LeetCode刷题】只出现一次的数字(Ⅰ、Ⅱ、Ⅲ)
|
6月前
每日一题——只出现一次的数字(II)
每日一题——只出现一次的数字(II)
每日一题——只出现一次的数字(II)
|
6月前
每日一题——只出现一次的数字
每日一题——只出现一次的数字
|
6月前
|
Java
每日一题《剑指offer》数组篇之和为S的两个数字
每日一题《剑指offer》数组篇之和为S的两个数字
43 0
每日一题《剑指offer》数组篇之和为S的两个数字
|
Java Python
leetcode每日一题.136:只出现一次的数字
leetcode每日一题.136:只出现一次的数字
56 0
|
存储
剑指offer 63. 和为S的两个数字
剑指offer 63. 和为S的两个数字
77 0
|
算法 C++ Python
每日算法系列【LeetCode 面试题 17.05】字母与数字
每日算法系列【LeetCode 面试题 17.05】字母与数字
LeetCode每日一题——902. 最大为 N 的数字组合
给定一个按 非递减顺序 排列的数字数组 digits 。你可以用任意次数 digits[i] 来写的数字。例如,如果 digits = [‘1’,‘3’,‘5’],我们可以写数字,如 ‘13’, ‘551’, 和 ‘1351315’。
96 0
LeetCode每日一题——902. 最大为 N 的数字组合
|
存储 Java
《LeetCode刷题》—136.只出现一次的数字
《LeetCode刷题》—136.只出现一次的数字
90 0
《LeetCode刷题》—136.只出现一次的数字