LeetCode-数组中数字出现的次数(单身狗问题)

简介: LeetCode-数组中数字出现的次数(单身狗问题)

题目要求

一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。编写一个函数找出这两个只出现一次的数字。


方法:


  • 由于其他数都出现两遍,把这些数异或在一起,结果为0->,所以数组中所有元素异或起来,实际是两个单身狗异或的结果记为ret
  • 由于两个单身狗不相同,所有异或的结果至少有1个比特位为1    (异或特点:对应比特位,相同为0,不同为1)
  • 所以可以对ret逐位判断,找到为1的比特位所在的位置进行分组。pos:两个比特位不同的位置(即异或的结果对应的比特位为1的位置:可任意位置,只要对应比特位为1即可)
  • 把数组中所有元素的pos位为1的放在一组,把pos位为0的放在另一组。认为最低位是第0位



图解

image.png

image.png


image.png


选择二进制序列中的哪一个比特位为1进行分组没有关系,只要是选择异或结果的二进制序列中某一位为1的进行分组即可



代码

>>    左移                 << 右移

int main()
{
    int arr[] = {1,1,2,5,6,5,7,8,7,8};
    int sz = sizeof(arr)/sizeof(arr[0]);
    int ret = 0;
    int i = 0;
    //将数组中的所有元素进行异或,得到的结果就是两个单身狗异或的结果
    for(i = 0;i<sz;i++)
    {
        ret^=arr[i];
    }
    //得到ret的二进制序列中比特位为1的位置
    int pos = 0;
    for(i = 0;i<32;i++)
    {
        //ret不断左移i位,与1相与,如果结果为1,说明该比特位为1
        if( ( (ret>>i) &1 ) ==1 )
        {
            pos = i;
            break;
        }
    }
    //将数组元素中二进制序列pos位为1的分到1组中,为0的分到另一组
    int m = 0;
    int n = 0;
    for(i = 0;i<sz;i++)
    {
        if( ( (arr[i] >>pos)&1 )== 1 )
        {
            //pos位置比特位为1和m异或
            m ^=arr[i];
        }
        else
        {
            //pos位置比特位为0和n异或
            n ^= arr[i];
        }
    }
    printf("%d %d\n",m,n);
    return 0;
}
复制代码

leetcode题目:

链接:剑指 Offer 56 - I. 数组中数字出现的次数 - 力扣(LeetCode) (leetcode-cn.com)

image.png

函数接口:


/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* singleNumbers(int* nums, int numsSize, int* returnSize){
}
复制代码


思路和上面的基本一致,但是要注意,这个题目要重新开辟一个空间用来保存两个单身狗,所以数组只需开辟两个大小的空间即可。

题目已经明确说明,动态开辟的数组不用我们释放,由调用者自己释放。所以我们只需要返回该数组的起始地址即可!!


注意点:动态开辟的数组的元素最初要初始化为0,否则最初动态开辟的数组的两个元素都是随机值,这样进行分组异或的话就会出错


->为数组元素初始化可以使用:直接使用下标初始化:

e.g. arr[0] = 0 arr[1] = 0

也可以使用memeset()函数进行初始化!


/**
 * Note: The returned array must be malloced, assume caller calls free(). ->后序我们不用释放,留个使用者释放
 */
int* singleNumbers(int* nums, int numsSize, int* returnSize){
        int i = 0;
        int ret = 0;
        //数组的元素进行异或,得到的结果就是两个单身狗异或的结果
        for(i = 0;i<numsSize;i++)
        {
            ret ^=nums[i];
        }
        //得到ret的二进制序列中比特位为1的位置pos
        int pos = 0;
        for(i = 0;i<32;i++)
        {
            //两个单身狗异或结果不断左移,直到找到比特位为1的位置
            if( ((ret>>i)&1) == 1 )
            {
                pos = i;
                break;
            }
        }
        //将数组元素比特位pos位置为1的分到一组,为0的分到另一组进行异或
        //开辟数组用来存储两个单身狗
        int* newarr = (int*)malloc(sizeof(int)*2);
        //注意:数组元素要初始化为0,否则不能通过,得到的是随机值
        newarr[0] = 0;
        newarr[1]= 0;
      for(i = 0;i<numsSize;i++)
    {
          //元素比特位pos位置为1的和数组第一个元素异或,为0的和数组第二个元素异或
        if( ((nums[i]>>pos)&1) == 1)
        {
            newarr[0] ^=nums[i];
        }
        else
        {
            newarr[1] ^=nums[i];
        }
    }
    //要返回数组中所含元素 ,让用户得知数组的元素个数。
    *returnSize = 2;
    return newarr;
}
复制代码

好了,今天就到这儿吧,欢迎大佬们点赞、收藏、评论呀!笔者水平有限,欢迎各位大佬批评指正!再次感谢!


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