解法:分组进行位运算
先做这道题136.只出现一次的数字
从头到尾异或数组中的每个数字,那么最终得到的结果就是两个只出现1次的数字的异或结果。由于这两个数字不一样,异或结果必然不为0,也就是说结果的二进制中存在至少1位为1,找到这个1的位置,我们可以根据该位是否为1将原数组分为两个子数组。分类的目的是把这两个数分到不同的子数组。因为两个相同的数字的任意一位都是相同的,所以它们不会被分开,会同时出现在同一组。
分成两个子数组后,每个子数组后包含一个只出现一次的数字,而其他数字都出现了两次。就将问题转化为如何在数组中找出唯一一个只出现一次的数字。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* singleNumbers(int* nums, int numsSize, int* returnSize){
// 第一次遍历,得到全体数字的异或结果
int temp = 0;
for(int i=0; i<numsSize; i++)
{
temp ^= nums[i];
}
// lowbit运算得到异或结果中的最后一位
// 第二次遍历以此将数组分为两部分,两部分中各含一个只出现1次的数
int lowbit = temp&-temp;
// 第二次遍历,得到结果
*returnSize = 2;
int *ret = malloc(sizeof(int)*(*returnSize));
ret[0] = ret[1] = 0;
for(int i=0; i<numsSize; i++)
{
if(lowbit & nums[i]) ret[0] ^= nums[i];
else ret[1] ^= nums[i];
}
return ret;
}
时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)。