一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。
例如:
有数组的元素是:1,2,3,4,5,1,2,3,4,6
只有5和6只出现1次,要找出5和6.
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
int team(int n, int count)//判断分组根据的是哪一位
{
while (count--)
{
n %= 2;
}
return n.
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
int len = sizeof(arr) / sizeof(*arr);
int fru = 0;
int s1 = 0;
int s2 = 0;
for (int i = 0; i < len; i++)
{
//将所有的数字异或在一起,这时的结果就是两个单独数字的异或结果
//这个结果中的为1的位就是两个数字不同的一位
//按照这个位进行分组,将数组分成两组,这时的两个数字就会被分到两组
//分组后进行组内异或就会找到这两个单独的数字
fru ^= arr[i];
}
int count = 1;//记录位数
while (fru%2 !=1)
{
count++;
fru /= 2;
}
for (int i = 0; i < len; i++)
{
if (team(arr[i], count) == 1)
{
s1 ^= arr[i];
}
else s2 ^= arr[i];
}
printf("%d %d\n", s1, s2);
return 0;
}
以上是一种单身狗问题的解决思路,下面我们针对leetcode上的问题进行改进
首先,以上的方法中,对于二进制中的位数的求法采用的是除以2的方式,这种方法不适用于数据中有负数的样例:
260. 只出现一次的数字 III - 力扣(LeetCode)
所以,我们将二进制位数问题用右移方式完成。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int team(int n,int count)
{
return (n >> count)&1 ;
}
int* singleNumber(int* nums, int numsSize, int* returnSize){
int t = 0;
int *ret = (int *)calloc(2,sizeof(int));
for(int i = 0; i < numsSize; i ++)
{
t ^= nums[i];
}
int count = 0;
for(int i = 0; i < 32; i ++)
{
if((t >> i)&1 == 1)
{
count = i;
break;
}
}
for(int i = 0; i < numsSize; i ++)
{
if(team(nums[i],count) == 1)
{
ret[0] ^= nums[i];
}
else if(team(nums[i],count) == 0)
{
ret[1] ^= nums[i];
}
}
*returnSize = 2;
return ret;
}
这样就可以适用于含有负数的样例了。