- 更多C语言的练习题可以点这个链接——C语言练习
1. 题目
- 题目的链接在这里——错误的集合
1.1 题目描述
- 集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复
- 给定一个数组 nums 代表了集合 S 发生错误后的结果。
- 请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
1.2 示例
2. 分析
2.1 思路1
2.1.1 分析
- 我们可以定义 i 和 j 来逐个比较
- 当比较的两个数字不相等的时候,就继续往后
- 直到两个数相等的时候停止,那么此时不管是 i 指向的地方还是 j 指向的地方都是重复的数字,
- 接着我们怎么求被覆盖的数字是多少呢
- 我们可以先把重复的数字去掉一个,接着把数组的每个元素加起来,记为sum1
- 接着再把原来没有重复的数组求和,记为sum2
- 最后sum2-sum1就是被覆盖掉的数字了
2.1.2 完整代码
static int arr[2] = {0};
int* findErrorNums(int* nums, int numsSize, int* returnSize)
{
int c = 0;
int flag = 1;
int sum1 = 0;
int sum2 = 0;
for (int i=0; i<numsSize-1; i++)
{
for (int j=i+1; j<numsSize; j++)
{
if (*(nums+i) == *(nums+j))
{
flag = 0;
c = *(nums+i);
break;
}//i和j对应的数字是否相等
}
if (flag == 0)
{
break;
}
}
for (int i=0; i<numsSize; i++)
{
sum1 += i+1;
sum2 += *(nums+i);
}//分别求和
arr[0] = c;//重复的数字
arr[1] = sum1-(sum2-c);//被覆盖的数字
*returnSize = 2;
return arr;
}
- 运行结果:
- 我们可以看到这样做思路虽然清晰,但是时间复杂度是比较大的
- 那么有没有更快的呢
2.2 思路2
2.2.1 分析
- 使用标记的方法
- 首先把数组都遍历一次,在此过程中记录每个数字出现的次数,如果哪个数字出现次数为2,则为重复的数字
- 如果有的数字出现次数为0,则为丢失的数字
2.2.2 完整代码
int* findErrorNums(int* nums, int numsSize, int* returnSize)
{
int* arr = (int*)malloc(sizeof(int) * (numsSize+1));//开辟标记的空间
memset(arr, 0, sizeof(int) * (numsSize+1));//初始化
int* num = (int*)malloc(sizeof(int) * 2);//开辟最后结果的空间
for (int i = 0; i < numsSize; i++)
{
arr[nums[i]] += 1;
}//开始标记
for (int j = 1; j < numsSize+1; j++)
{
if (arr[j] == 2)
{
num[0] = j;
}
else if (arr[j] == 0)
{
num[1] = j;
}
}//查看标记
*returnSize = 2;
return num;
}
- 运行结果:
最后,
恭喜你又遥遥领先了别人!!