经典算法题之 找出一个数组中的两个“单身狗”

简介: 经典算法题之 找出一个数组中的两个“单身狗”

剑指 Offer 56 - I. 数组中数字出现的次数 - 力扣(LeetCode)


思路:


       由于这个数组中有两个数字只出现了一次,其余数字都出现了两次,而根据按位异或的特性知道,两个相同的数字按位异或的结果是0,相异的数字按位异或是1,任何数与0按位异或都等于这个数本身,正因为其他数字都出现了两次,所以出现了两次的数字全部按位异或得到的结果是0,所以我们把这个数组的所有元素按位异或到一起得到的结果是这两个只出现了一次的数字按位异或的结果ret,这时我们需要把这两个数字分开。由于变量在内存中是以二进制的形式存储的,而二进制只有0和1,所以我们需要找到这个ret任意一个二进制位为1的位置m,由于ret是两个不同的数字按位异或得到的结果,而位置m是1,所以这两个不同的数字的位置m一定不同,而相同的数字位置m的值一定相同,不影响结果,所以遍历这个数组,把数组中m位置二进制位为1的所有元素按位异或到一起的结果就是其中一个只出现了一次的数字,再把数组中m位置二进制位位0的所有元素按位异或到一起的结果就是另一个只出现了一次的数字。


      建议参考下面代码梳理上述思路。


int main()
{
  int arr[] = { 1,2,3,4,5,1,2,3 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  int i = 0;
  int ret = 0;
  for (i = 0; i < sz; i++)
  {
    ret ^= arr[i];//ret得到的结果是两个“单身狗”按位异或的结果
  }
  //分离
  int m = 0;
  for (i = 0; i < 32; i++)//一个整形再二进制里有32个比特位,故需要遍历32个位置,但找到一个1 
                            //之后就无需再找了
  {
    if (((ret >> i) & 1) == 1)
    {
      m = i;//m的位置为1,由于ret的m位置为1,而ret是有两个不同的数字按位异或得到的,所以
            //这两个数字的m位置的值一定不同
      break;
    }
  }
  int x = 0;
  int y = 0;
  for (i = 0; i < sz; i++)
  {
    if (((arr[i] >> m) & 1) == 1)
    {
      x ^= arr[i];//由于x是0,所以不影响结果,得到的结果是其中一个“单身狗”
    }
    else
    {
      y ^= arr[i];//得到的结果是另一个“单身狗”
    }
  }
  printf("x=%d,y=%d", x, y);
  return 0;
}


如果是再力扣上做题,我们应该改一下形式,如下面的代码。


int* singleNumbers(int* arr, int sz, int* returnSize){
    int* p=(int*)malloc(sizeof(int)*2);
    *returnSize=2;
    int ret = 0;
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    ret ^= arr[i];
  }
  //分离
  int m = 0;
  for (i = 0; i < sz; i++)
  {
    if (((ret >> i) & 1) == 1)
    {
      m = i;
      break;
    }
  }
  int x = 0;
  int y = 0;
  for (i = 0; i < sz; i++)
  {
    if (((arr[i] >> m) & 1) == 1)
    {
      x ^= arr[i];
    }
    else
    {
      y ^= arr[i];
    }
  }
    p[0]=x;
    p[1]=y;
    return p;
}
相关文章
|
1月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
38 0
|
3月前
|
算法 测试技术
【算法】二分算法——寻找旋转排序数组中的最小值
【算法】二分算法——寻找旋转排序数组中的最小值
|
3月前
|
算法
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置
|
1月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
27 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
1月前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
20 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
|
5月前
|
存储 算法 Go
算法学习:数组 vs 链表
算法学习:数组 vs 链表
62 0
|
3月前
|
存储 算法 Java
深入算法基础二分查找数组
文章深入学习了二分查找算法的基础,通过实战例子详细解释了算法的逻辑流程,强调了确定合法搜索边界的重要性,并提供了Java语言的代码实现。
深入算法基础二分查找数组
|
3月前
|
算法
【Azure Developer】完成算法第4版书中,第一节基础编码中的数组函数 histogrm()
【Azure Developer】完成算法第4版书中,第一节基础编码中的数组函数 histogrm()
|
3月前
|
算法
【算法】模拟算法——外观数组(medium)
【算法】模拟算法——外观数组(medium)
|
3月前
|
算法
【算法】前缀和——除自身以外数组的乘积
【算法】前缀和——除自身以外数组的乘积
下一篇
无影云桌面