1. 题目描述
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例 1:
输入:nums = [1,2,2,4]
输出:[2,3]
示例 2:
输入:nums = [1,1]
输出:[1,2]
提示:
2 <= nums.length <= 104
1 <= nums[i] <= 10
https://leetcode.cn/problems/set-mismatch/description/该题目的链接放这里哦~
2. 解题思路
1.当我们读完题目后,我们知道我们要做俩件事,一就是找到丢失的数字和重复的数字放到一个数组中并输出。
2.我们要注意到的是题目并没有告诉我们这个错误的集合是一个有序(升序)的数组,所以我们不妨将这个错误的数组先进行排序。
3.当我们将这个数组进行升序后,我们会很轻松的知道重复的数字是紧挨在一起的,那我们就只要从数组开端开始判断相邻俩个元素是否相同,若相同那我们就找到重复的元素了。
4.我们也可以很轻松的注意到数组元素与数组下标的关系就是n(元素)=i(数组下标)+1
那我们是不是就只要判断n==i+1就可以了呢?如果!=那我们是不是就找到丢失的元素了呢?代码这样实现~
5.其实这种思路是没有问题的,但我们还要注意到有重复元素,所以我们要在找到重复元素后将其后面的元素整体往前挪一位覆盖前面的一个重复元素(画个图理解一下)
这种情况我们可以知道缺失的数字是4,好像不用往前覆盖就可以找到,那如果是这样呢?
如果我们不往前覆盖的话,上面的代码逻辑求出来丢失的元素就是3了。
3. 代码实现
再让我们结合整体代码加深一下理解吧~
int* findErrorNums(int* nums, int numsSize, int* returnSize) { int i=0; int j=0; int* errorNums =malloc(sizeof(int) * 2); for(i=0;i<numsSize-1;i++) { for(j=i+1;j<numsSize;j++) { if(nums[i]>nums[j]) { int tmp=0; tmp=nums[i]; nums[i]=nums[j]; nums[j]=tmp; } } }//排序 for(i=0;i<numsSize-1;i++) { if(nums[i]==nums[i+1]) { errorNums[0]=nums[i];//找重复的元素 for(j=i;j<numsSize-1;j++) { nums[j]=nums[j+1]; }//找到后将重复后面的元素整体往前挪 break; } } for(i=0;i<numsSize;i++) { if(nums[i]!=i+1) { errorNums[1]=i+1; break; } }//找丢失的元素 *returnSize=2; return errorNums; }
注意:在leetcode上这个题目只注重核心逻辑代码的实现(数据都不用自己给),main函数在系统后台,这里呈现的是一个函数。
还要注意到malloc是动态开辟的内存(上面是在堆上开辟了一块8字节的内存空间),不会因为函数的调用结束而被回收掉,而是需要手动的调用free把空间释放掉(如果我们在函数中使用平常的方式开辟一片空间存放数组errorNums,随着函数的调用结束,开辟的空间会被系统回收掉。)