描述:
集合 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] <= 104
答案1:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int cmp(int* a, int* b) { return *a - *b; }
int* findErrorNums(int* nums, int numsSize, int* returnSize) {
int* sum = malloc(sizeof(int) * 2);
*returnSize = 2; //表示返回的数组长度
int i, s;
qsort(nums, numsSize, sizeof(int), cmp);
int prev = 0;//prev记录当前遍历数组元素的前一项
for (int i = 0; i < numsSize; i++) {
int curr = nums[i];
if (curr == prev) {//后一项与前一项相等时就是重复的数字
sum[0] = prev;
} else if (curr - prev > 1) {//当后一项-前一项>1时,sum[1]是丢失的数字
sum[1] = prev + 1;
}
prev = curr;
}
if (nums[numsSize - 1] != numsSize) {//当最后一项不是n时,则丢失的数字是n
sum[1] = numsSize;
}
return sum;
}
详解1:
先将数组中元素按升序排列,用prev记录前一项,用curr记录当前访问到的数组元素。
若当前访问值与prev相等,则表示该元素重复,当前元素-prev>1时,说明缺失的是prev+1这一元素值。
注意极端情况,当最后一项数组元素值不是n时说明缺失数组元素n。
答案2:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
//用哈希表记录每个元素在数组中出现的次数,然后遍历,出现2次的就是重复的元素,出现1次的就是丢失的元素。
// int cmp(int* a, int* b) { return *a - *b; }
struct HashTable { //定义哈希表的结构体
int key, val;
UT_hash_handle hh; //加上这句才能引用头文件中的一些函数
};
int* findErrorNums(int* nums, int numsSize, int* returnSize) {
int* sum = malloc(sizeof(int) * 2);
*returnSize = 2; //表示返回的数组长度
struct HashTable* hashTable = NULL; //初始化哈希表
for (int i = 0; i < numsSize; i++) {
struct HashTable* tmp;
HASH_FIND_INT(hashTable, &nums[i],
tmp); //插入之前需要先查找是否该元素不存在
if (tmp == NULL) {
tmp = malloc(sizeof(struct HashTable));
tmp->key = nums[i], tmp->val = 1;//nums[i]的位置上关键字值为1
HASH_ADD_INT(hashTable, key, tmp);
} else {
tmp->val++;//重复出现的关键字值为2
}
}
for (int i = 1; i <= numsSize; i++) {//哈希表从1开始
struct HashTable* tmp;
HASH_FIND_INT(hashTable, &i, tmp);
if (tmp == NULL) {//空的是丢失的元素
sum[1] = i;
} else if (tmp->val == 2) {//2的是重复的元素
sum[0] = i;
}
}
return sum;
}
详解2:
采用哈希表实现,哈希表内容详见: