C语言练习:(力扣645)错误的集合

2024-02-28 22:20

本文主要是介绍C语言练习:(力扣645)错误的集合,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接:645. 错误的集合 - 力扣(LeetCode)

集合 s 包含从 1n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

思路解析:

本题可以考虑两个思路:

  • 数学方法

先对数组进行由小到大排序,因为缺失的数值介于前一个数值和后一个数值中间,并且在不缺失的情况下相邻两个数值差值为1,如果有数值重复,那么重复的数值和下一个不同的数值之间的差值为2,所以需要记录前一个数值存储在变量prev

📌

注意prev初始化为0,因为存在数组中缺失的数值为1,而如果数组中只有两个元素,那么最大值为2,此时在数组中找不到一个数值使得重复的数值和下一个的不同两个数值差值为2

先找到重复的数值,即下一个元素和当前元素cur相同时,存储当前数值cur到新数组的第一个元素的位置,更新prev为当前的重复数值

再继续循环,若当前数值与prev中存的数值差值大于1,说明此时已经找完了重复元素,因为不缺失数值时相邻两个数值差值为1,而此时prev中的数值和当前数值差值大于1,说明prev中的数值+1即为缺失的数值,将prev + 1存储新数组的第二个位置后更新prev

当走完该循环时,还需要注意一个问题:如果缺失的数值是数组的最大值(例如122,缺失3),此时需要单独判断,因为不存在一个数值使得后一个元素和当前元素差值为2,所以当数组的最后一个元素不等于数组的大小时,此时即为缺失数组最大值

  • 异或运算

本题同样可以考虑异或运算对重复数值和缺失数值分堆来求解,但是直接在原数组中对元素进行异或不可取

考虑到以下规律:

在原数组中,观察到重复的数值和缺失的数值都出现偶数次,而其他数值均出现奇数次,如果构造一个1~n的不缺数的数组和原数组组合,那么重复的数值和缺失的数值都出现奇数次,而其他数值均出现偶数次,在异或运算中,相同的两个数异或可以得到a^a = 0,而a^0 = a,故此时对构造的数组和原数组进行整体异或可以得到重复的数值和缺失的数值异或的结果值

故采用先构造一个数组和原数组进行整体异或,得到一个返回值ret即为重复数值和缺失数值的异或结果,因为异或运算的本质是找出两个操作数二进制位不同的位置,所以计算结果的二进制位为1的位置即为重复的数值和缺失的数值相异的位置,此时可以采用循环结合右移运算符找到相异的位置(二进制位数的下标,例如1和5中倒数第三位不同),但是本次将采用返回值与返回值的负数形式相与计算得出最低的不同位,即int position = ret & (-ret);,但是注意该语句计算的不是不同的下标位置,而是具体的值,但是该值的二进制值中为1的位置为对应的两个数不同的位置

找到最低的不同位之后,通过原数组和构造的数组中的元素与不同位的数值相与运算得到结果为0和不为0的数值,将二者分堆即可分出重复的数值和缺失的数值(因为重复的数值和缺失的数值不相同,所以二者不可能在同一堆中)

最后,因为暂时不知道重复的数值和缺失的数值具体所在的位置,所以需要遍历原数组确定重复的数值存储在新数组的第一个元素的位置,缺失的数值则放置到新数组的第二个位置

参考答案:

排序+调整(数学方法)

/** @lc app=leetcode.cn id=645 lang=c** [645] 错误的集合*/// @lc code=start
/*** Note: The returned array must be malloced, assume caller calls free().*/int cmp(const void *p1, const void *p2)
{return (*(int *)p1 - *(int *)p2);
}
int *findErrorNums(int *nums, int numsSize, int *returnSize)
{// 对已知数组进行从小到大排序qsort(nums, numsSize, sizeof(int), cmp);int *p = (int *)malloc(sizeof(int) * 2);// 定义变量记录数组中上一个元素的位置,便于计算缺失的数值int prev = 0;// 遍历数组// 1.如果找出的元素与prev中的值差值大于1,说明当前缺失的元素即为prev当前值的后一位数值// 2.如果找出的元素与prev中的值相等,说明遇到了相同元素for (int i = 0; i < numsSize; i++){int cur = nums[i]; // 遍历数组if (cur == prev){// 如果相同则表示遇到相同元素p[0] = cur; // 记录相同元素}else if (cur - prev > 1){// 如果不同且满足二者差值大于1时,则表示中间有缺失元素,并且缺失元素即为prev当前大小+1p[1] = prev + 1;}prev = cur; // 更新prev}// 存在一种情况:数组中最后一个数值小于数组长度if (nums[numsSize - 1] != numsSize){// 数组中缺失的数值为数组的最大值p[1] = numsSize;}*returnSize = 2;return p;
}
// @lc code=end

异或运算

/** @lc app=leetcode.cn id=645 lang=c** [645] 错误的集合*/// @lc code=start
/*** Note: The returned array must be malloced, assume caller calls free().*/int *findErrorNums(int *nums, int numsSize, int *returnSize)
{int *p = (int *)malloc(sizeof(int) * 2);int ret = 0;// 构造一个1-n的不缺数值的数组与原来的数组进行整体异或for (int i = 1; i <= numsSize; i++){// 将不缺数的数组进行整体异或ret ^= i;// 将缺数的数组与不缺数的数组进行整体异或ret ^= nums[i - 1];}// 当前ret中存储的值为重复数值和缺失数值异或的结果// 找出重复数值和缺失数值二者最低的不同位// 可以代替原来的移位找最低不同位算法int position = ret & (-ret);// 定义两个数值分别存储重复数值和缺失的数值int num1 = 0;int num2 = 0;// 根据最低的不同二进制位对原数组进行分组for (int i = 0; i < numsSize; i++){if ((nums[i] & position) == 0){num1 ^= nums[i];}else{num2 ^= nums[i];}}// 根据最低的不同二进制位对构造数组进行分组for (int i = 1; i <= numsSize; i++){if ((i & position) == 0){num1 ^= i;}else{num2 ^= i;}}// 因为当前不确定重复的数值和缺失的数值在num1和还是num2,所以需要与原数组进行再一次的比较找出重复数值,剩下的就是缺失的数值*returnSize = 2;for (int i = 0; i < numsSize; i++){if (nums[i] == num1){p[0] = num1;p[1] = num2;return p;}}// 如果已经确定则直接返回p[0] = num2;p[1] = num1;return p;
}
// @lc code=end

这篇关于C语言练习:(力扣645)错误的集合的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/756795

相关文章

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复

Python struct.unpack() 用法及常见错误详解

《Pythonstruct.unpack()用法及常见错误详解》struct.unpack()是Python中用于将二进制数据(字节序列)解析为Python数据类型的函数,通常与struct.pa... 目录一、函数语法二、格式字符串详解三、使用示例示例 1:解析整数和浮点数示例 2:解析字符串示例 3:解

CentOS 7 YUM源配置错误的解决方法

《CentOS7YUM源配置错误的解决方法》在使用虚拟机安装CentOS7系统时,我们可能会遇到YUM源配置错误的问题,导致无法正常下载软件包,为了解决这个问题,我们可以替换YUM源... 目录一、备份原有的 YUM 源配置文件二、选择并配置新的 YUM 源三、清理旧的缓存并重建新的缓存四、验证 YUM 源

Go语言中使用JWT进行身份验证的几种方式

《Go语言中使用JWT进行身份验证的几种方式》本文主要介绍了Go语言中使用JWT进行身份验证的几种方式,包括dgrijalva/jwt-go、golang-jwt/jwt、lestrrat-go/jw... 目录简介1. github.com/dgrijalva/jwt-go安装:使用示例:解释:2. gi

python3 pip终端出现错误解决的方法详解

《python3pip终端出现错误解决的方法详解》这篇文章主要为大家详细介绍了python3pip如果在终端出现错误该如何解决,文中的示例方法讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下... 目录前言一、查看是否已安装pip二、查看是否添加至环境变量1.查看环境变量是http://www.cppcns