集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/set-mismatch
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
一、明确异或运算支持交换律与结合律。
x^x=0,x^x^x=x,x^x^x^y=x^y。
二、原数组除了错误数字,其余每个数字出现一次,所以没有出现的数字与错误的数字的奇偶性相同,与其他数字的奇偶性相异,所以在原数组后再加上正确数字组成的数组,并用xor进行异或判断,可以得出这缺失数字异或错误数字的结果。
三、两个数字相异或得到的结果,是两个数字都没有的位,取其中的最低位,最低位计算的方法是lowbit=xor&(-xor)。
四、设num1和num2两个变量,用lowbit位与数组中的每一个数字,当lowbit&num!=0时,num1^=num,当lowbit&num==0时,num2^=num,可以得到缺失的数字和错误的数字。
五、用num1遍历一次原数组,可以区分出缺失数与错误数。
int* findErrorNums(int* nums, int numsSize, int* returnSize)
{
//新增需要的空间
int *errornumS = (int *)malloc(sizeof(int)*2);
assert(errornumS&&nums);
*returnSize = 2;
//增加数组内容
int i = 1;
int xor=0;
//异或得到x异或y的结果
for (i = 1; i <= numsSize; i++)
{
xor = xor^i;
xor = xor^nums[i-1];
}
//计算x和y的最小位;
int lowbit = (-xor)&xor;
//取得两个数
int num1=0, num2=0;
//遍历前数组
for (i = 0; i<numsSize; i++)
{
if (lowbit&nums[i])
{
num1 = num1^nums[i];
}
else
{
num2 = num2^nums[i];
}
}
//遍历后数组
for (i = 1; i<=numsSize; i++)
{
if (lowbit&i)
{
num1 = num1^i;
}
else
{
num2 = num2^i;
}
}
//区分缺失数与错误数
int flag = 0;
for (i = 0; i < numsSize; i++)
{
if (num1 == nums[i])
{
errornumS[0] = num1;
errornumS[1] = num2;
flag = 1;
break;
}
}
if (flag == 0)
{
errornumS[0] = num2;
errornumS[1] = num1;
}
return errornumS;
}
int main()
{
int arr[] = { 4,2,2,1};
int sz = sizeof(arr) / sizeof(arr[0]);
int* a1 = NULL;
int a2;
a1 = findErrorNums(arr, sz, &a2);
printf("[%d,%d]", a1[0], a1[1]);
SYS;
R0;
}