刷爆leetcode第十二期 0026 数组中数字出现的次数

简介: 刷爆leetcode第十二期 0026 数组中数字出现的次数

编号0026 数组中数字出现的次数


一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。


题目示例如下


b57a58008213411b94d83226b0319137.png


这里其实是一道我一个月之前做的题目


在学弟的博客里刚好看到了 又翻了翻自己的博客 好像没有这道题目的题解


刚看到第一眼还以为自己不会了 慢慢梳理了下思路


这里其实又很多种做法 排序之后对比前后数字啊


使用一个很大的数组将它们依次赋值给数组里面对应的值啦


当然这里最优的解法应该是异或法


我们想想看将整个数组里面所有的元素异或 是不是就能得到那两个不同数字的异或了


(因为相同的数字异或都变成0了)


那么首先 我们可以将整个数组异或下来得到一个数字


就像这样


    //首先使用一个测试数字0  让他一一和数组里面的异或 
    //异或完毕之后就会只剩下两个数字的异或结果
    int test = 0;
    int i = 0;
    for(i=0;i<numsSize;i++)
    {
        test^=nums[i];
    }


之后得到这个结果了之后怎么办呢?


我们之后要将整个数组分成两个 尤其是这两个不同的数字要在不同的组别中


那么要怎么分呢?


这也是这个题目唯一的难点


我们可以利用 ‘位’ 来分组


我们都知道了 test是这两个数字异或的结果


那么说明了什么呢?


是不是这个数字的二进制中为1的位 一定是这两个数的位不同的


仔细思考下异或的性质


那么想明白这个事情之后就简单了


我们开始利用这个性质分组


首先找出不同的位在哪里(1)


    // 之后我们可以将这个数组分成两个 (这其中两个数字要不在同一个地方)
    // 这两个数字异或结果为1的地方一定是不相等的  
    // 所以我们首先要找出第一个出现1的地方
    // 我们使用count来计数这个1出现的地方
    int count =0;
    for(i=0;i<32;i++)
    {
        if((test>>i)&1==1)
        {
            break;
        }
        count++;
    }


再之后分别异或下就可以了


    // 之后我们用count将数组分组 分别异或两个数得到的就是两个数了
    int num1 = test;
    int num2 = test;
    for(i=0;i<numsSize;i++)
    {
        if((nums[i]>>count)&1 == 1)
        {
            num1^=nums[i];
        }
        else
        {
            num2^=nums[i];
        }
    }
    //存放到动态数组里面
    int* a = (int*)malloc(sizeof(int)*2);
    a[0]=num1;
    a[1]=num2;
    // 最后设定下返回数组的大小就可以
    *returnSize = 2;
    return a;
}

整体代码表示如下


/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* singleNumbers(int* nums, int numsSize, int* returnSize)
{
    //首先使用一个测试数字0  让他一一和数组里面的异或 
    //异或完毕之后就会只剩下两个数字的异或结果
    int test = 0;
    int i = 0;
    for(i=0;i<numsSize;i++)
    {
        test^=nums[i];
    }
    // 之后我们可以将这个数组分成两个 (这其中两个数字要不在同一个地方)
    // 这两个数字异或结果为1的地方一定是不相等的  
    // 所以我们首先要找出第一个出现1的地方
    // 我们使用count来计数这个1出现的地方
    int count =0;
    for(i=0;i<32;i++)
    {
        if((test>>i)&1==1)
        {
            break;
        }
        count++;
    }
    // 之后我们用count将数组分组 分别异或两个数得到的就是两个数了
    int num1 = test;
    int num2 = test;
    for(i=0;i<numsSize;i++)
    {
        if((nums[i]>>count)&1 == 1)
        {
            num1^=nums[i];
        }
        else
        {
            num2^=nums[i];
        }
    }
    //存放到动态数组里面
    int* a = (int*)malloc(sizeof(int)*2);
    a[0]=num1;
    a[1]=num2;
    // 最后设定下返回数组的大小就可以
    *returnSize = 2;
    return a;
}


总的来说还是很开心的! 一个月前死活想不出来的题目现在看一眼有思路 十分钟就可以敲出来了


继续加油!

相关文章
|
1月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
38 0
|
3月前
|
算法
LeetCode第53题最大子数组和
LeetCode第53题"最大子数组和"的解题方法,利用动态规划思想,通过一次遍历数组,维护到当前元素为止的最大子数组和,有效避免了复杂度更高的暴力解法。
LeetCode第53题最大子数组和
|
3月前
|
存储 Java API
LeetCode------合并两个有序数组(4)【数组】
这篇文章介绍了LeetCode上的"合并两个有序数组"问题,并提供了三种解法:第一种是使用Java的Arrays.sort()方法直接对合并后的数组进行排序;第二种是使用辅助数组和双指针技术进行合并;第三种则是从后向前的双指针方法,避免了使用额外的辅助数组。
LeetCode------合并两个有序数组(4)【数组】
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
114 2
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 03. 数组中重复的数字
解决剑指Offer题目 "数组中重复的数字" 的Python实现方法,通过使用字典来记录数组中每个数字的出现次数,快速找出重复的数字。
39 1
LeetCode------找到所有数组中消失的数字(6)【数组】
这篇文章介绍了LeetCode上的"找到所有数组中消失的数字"问题,提供了一种解法,通过两次遍历来找出所有未在数组中出现的数字:第一次遍历将数组中的每个数字对应位置的值增加数组长度,第二次遍历找出所有未被增加的数字,即缺失的数字。
|
3月前
|
前端开发
LeetCode------移动零(5)【数组】
这篇文章介绍了LeetCode上的"移动零"问题,提出了一种使用双指针的原地操作解法,该方法首先将非零元素移动到数组前端并保持相对顺序,然后填充后续位置为零,以达到题目要求。
|
1月前
【LeetCode-每日一题】 删除排序数组中的重复项
【LeetCode-每日一题】 删除排序数组中的重复项
19 4
|
1月前
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
19 0
Leetcode第三十三题(搜索旋转排序数组)
|
1月前
|
算法 C++
Leetcode第53题(最大子数组和)
这篇文章介绍了LeetCode第53题“最大子数组和”的动态规划解法,提供了详细的状态转移方程和C++代码实现,并讨论了其他算法如贪心、分治、改进动态规划和分块累计法。
58 0