目录
前言
如题目所言,这篇文章的内容是在一组数中寻找只出现一次的数,比如 1234123456,在这组数中, 5和6 只出现了一次,所以我们将其称为“单身狗”,那么如何才能从这组数组中找单个出现的元素呢?
其实我们只需要三步即可。
1,首先,对所有数字进行异或,然后得到的两个单独的元素的异或值。
2,对于这个值,其二进制值一定有一位是不同的,我们需要找到该值,暂且将该值所在的位记为 flag。
3,所以我们将这个数组中其他元素分为两组,一组是flag位为1 的,另一组是该位为 0 的,因为这两个单独的元素,被分为两组,所以最后这两组分别进行异或,即可得到这两个单独元素。
------------------------------------正文如下----------------------------------
一,问题分析
首先,我们应该知道,对于一组数,如果其中只有一个单独的数字,那么我们将所有的元素进行异或,然后得到便是那个单独的元素,所以这里我们便用这个原理。将原先的一组数分为两组数,然后分别进行异或,最后得到的便是我们需要的单独出现的那个元素。
二,具体实现
1.1实现方法
首先,对于一组数首先,我们需要将其内容进行异或,然后得到两个单独的元素的异或值 ret 。
然后,我们需要确定该异或值二进制哪一位为 1,为我们后面分组做选择。如下所示,我们用到了右移操作符,在找到哪一位为 1 之后,我们使用 pos 将该位置记下来,而在这里判断哪一位为 1 的时候,又用到了按位与 & 操作符,用以简化操作:
第三步,我们对于这组数中的每个元素在右移pos位后,再与 1 按位与,得到数与 1 比较是否相等,然后相等的元素分为一组,不相等的元素分为一组,这两组元素分别进行异或,最后得到的是两个单独的数字。
然后,最后只需要我们打印就可以了,当然这个方法暂时来说,只适用于一组数中有两个单独数字的,如果一组数中单身狗元素比较多,那么这种方法是不适用的。
1.2实现代码
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int ret = 0;
//1.求出 5^6 的值
for (i = 0; i < sz; i++)
{
ret = ret ^ arr[i];
}
//得到 5^6 第几位为 1
int pos = 0;
for (i = 0; i < 32; i++)
{
if (((ret >> i) & 1) == 1)
pos = i;
break;
}
//分组
int m = 0;
int n = 0;
for (i = 0; i < sz; i++)
{
if (1 == ((arr[i] >> pos) & 1))
{
m = m ^ arr[i];
}
else
{
n = n ^ arr[i];
}
}
printf("%d %d",m,n);
return 0;
}
好的,那么如果想要实现三个以上单个元素,其实是有比较简单的方法的,就是用两个循环去实现呢,但是那样做的话效率是很低的,但是是可以实现多元素的。如有需要,可以留言哦!