错误的集合(c语言)

题目链接:645. 错误的集合 - 力扣(LeetCode) (leetcode-cn.com)icon-default.png?t=M0H8https://leetcode-cn.com/problems/set-mismatch/

题目描述:集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。

给定一个数组 nums 代表了集合 S 发生错误后的结果。

请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

示例 1:

输入:nums = [1,2,2,4]
输出:[2,3]

法一:排序

(1)先把nums数组按升序排序,然后比较相邻两个元素,如果相等,则找到重复元素

(2)找到丢失的元素比较麻烦,如果丢失的这个数是大于1小于n的,由于数组已经排序,则一定存在两个相邻的数字的差值为2,则丢失的数字在两个相邻数字的中间

比如1,2,2,4,我们可以看到2和4是相差2,,则丢失的数字是2和4之间也就是3

当丢失的数字是1时,我们一开始需要把上一个元素初始化为0,比如用lastone标记上一个元素,数组是2,2,我们可以看到重复数字是2,丢失是1,一开始用cur标记第一个2,然后cur-lastone>1因为cur=2,lastone一开始是被初始化为0的,所以丢失的数字是lastone+1;也就是1

代码:

int cmp(int* a, int* b) {
    return *a - *b;
}

int* findErrorNums(int* nums, int numsSize, int* returnSize) {
    int* ret = malloc(sizeof(int) * 2);
    *returnSize = 2;
    qsort(nums, numsSize, sizeof(int), cmp);
    int lastone = 0;
    for (int i = 0; i < numsSize; i++) {
        int cur = nums[i];
        if (cur == lastone) {
            ret[0] = lastone;
        } else if (cur -lastone > 1) {
            ret[1] = lastone + 1;
        }
        lastone = cur;
    }
    if(nums[numsSize-1]!=numsSize)
    ret[1]=numsSize;
    return ret;
}

法二:哈希表

以1,2,2,4为例,我们例外设一个5长度的数组int arr[5],然后因为是1到n的数字,就把1到n作为下标,放到arr里并标记为1,也就是arr[nums[i]]=1,到最后2,2会被重复标记为1,则我们找到重复数字2,

然后将1加到n减去当前数组数据总和再加重复数字,就是丢失的数字

以上面1,2,2,4为例就是:

(1+2+3+4)-(1+2+2+4)+2=3

代码如下:

int* findErrorNums(int* nums, int numsSize, int* returnSize)
{
   *returnSize=2;
   int*ret=(int*)calloc(*returnSize,sizeof(int));
   int*arr=(int*)calloc(numsSize+1,sizeof(int));
   int old_sum=0,cur_sum=0,i=0;
    for(i=0;i<numsSize;i++)
    {
        if(arr[nums[i]]==1)
        {
            ret[0]=nums[i];
        }
        arr[nums[i]]=1;
        old_sum+=i+1;
        cur_sum+=nums[i];
    }
    ret[1]=old_sum-(cur_sum-ret[0]);
    free(arr);
    return ret;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值