博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LeetCode算法题-Set Mismatch(Java实现)
阅读量:6250 次
发布时间:2019-06-22

本文共 3228 字,大约阅读时间需要 10 分钟。

这是悦乐书的第279次更新,第295篇原创

01 看题和准备

今天介绍的是LeetCode算法题中Easy级别的第147题(顺位题号是645)。集合S最初包含从1到n的数字。 但不幸的是,由于数据错误,集合中的一个数字被复制到集合中的另一个数字,这导致重复一个数字而丢失另一个数字。给定一个数组nums,表示错误后该集的数据状态。要求先找到两次出现的数字,然后找到丢失的数数字,最后以数组的形式返回它们。例如:

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

输出:[2,3]

注意:

  • 给定的数组大小将在[2,10000]范围内。

  • 给定数组的数字无序。

本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

02 第一种解法

题目的意思是根据给出的数组,找出两个数,第一个数是该数组中重复出现的那个数,第二个数是该数组中缺失的那个数,也就是说最后返回的结果数组,两个数是有先后顺序的。

先对数组排序,然后从第二位开始遍历数组,如果当前一位与前一位相等,说明重复了,那么第一位数就找到了。如果当前元素比前一位元素加1后还要大,说明前一位元素是重复出现的那个数的第二个,也就是要找的缺失的那个数。

但是,还有两种特殊情况需要考虑,因为题目并不能保证数组首尾不缺少元素。第一,nums的第一位是不是从1开始?如果不是,那么第二个数就是1。第二,nums的最后一位元素是不是和数组长度相等?如果不相等,那么第二个数就是数组的长度。

此解法的时间复杂度是O(nlog(n)),空间复杂度是O(1)。

public int[] findErrorNums(int[] nums) {    // 排序    Arrays.sort(nums);    int[] result = new int[2];    for (int i=1; i
nums[i-1]+1) { // 第二个数,缺失的那个数 result[1] = nums[i-1]+1; } } // 数组第一个元素不是1 if (nums[0] != 1) { result[1] = 1; } else if (nums[nums.length-1] != nums.length) { // 数组最后一个元素不是数组的长度 result[1] = nums.length; } return result;}

03 第二种解法

我们也可以不排序,使用HashMap。先将数组的元素都添加进map中,以元素值为key,出现次数为value。然后开始循环,从0到数组的长度,如果map中包含当前索引值加1,并且它出现的次数为2次,那么第一个数就是该元素,否则第二个元素就是当前缺失的索引值加1。

此解法的时间复杂度是O(n),最坏情况是O(n^2),空间复杂度是O(n)。

public int[] findErrorNums(int[] nums) {    int[] result = new int[2];    Map
map = new HashMap
(); for (int num : nums) { map.put(num, map.getOrDefault(num, 0)+1); } for (int i=0; i

04 第三种解法

我们也可以不使用HashMap,使用数组进行代替。思路与第二种解法类似。

此解法的时间复杂度是O(n),空间复杂度是O(n)。

public int[] findErrorNums(int[] nums) {    int[] result = new int[2];    // 新建一个数组,长度比nums大1    int[] arr = new int[nums.length+1];    for (int i=0; i

05 第四种解法

我们还可以使用减法。先将数组元素正常情况下的元素之和算出来,因为是从1到n的数,是一个公差为1的等差数列,可以直接套用等差数列求和的公式来计算和,然后用算出来的和减去数组中的每一个元素,最后和可能是正1,也可能是负1,因为数组中有重复元素,也就可能多1或者少1,也即是重复项元素值多1或者少1,所以缺失的那个数可以直接使用最后的和与重复项元素相加得到。

此解法的时间复杂度是O(n),空间复杂度是O(n)。

public int[] findErrorNums(int[] nums) {    int[] result = new int[2];    // 定义一个HashSet    Set
set = new HashSet
(); // 等差数列求和公式 long sum = nums.length*(nums.length+1)/2; for (int i=0; i

06 第五种解法

我们可以对原数组进行标记,将元素变成负数,如果遇到的元素是小于0的,说明已经对该元素变过一次负数,也就是说该元素重复了,最后在遍历一次数组,如果遇到大于0的数,表明在该位置缺少一个元素。

此解法的时间复杂度是O(n),空间复杂度是O(1)。

public int[] findErrorNums(int[] nums) {    int[] result = new int[2];    for (int num : nums) {        if (nums[Math.abs(num)-1] < 0) {            // 已经转过一次负数的数,表明重复            result[0] = Math.abs(num);        } else {            // 将所有元素转为负数            nums[Math.abs(num)-1] *= -1;        }    }    for (int i=1; i
0) { result[1] = i+1; } } return result;}

07 第六种解法

此解法是使用异或运算,来自讨论区。传送门:

public int[] findErrorNums(int[] nums) {    int[] ans = new int[2];    for(int i = 0; i < nums.length; i++) {        int val = Math.abs(nums[i]);        ans[1] ^= (i+1) ^ val;        if (nums[val-1] < 0) ans[0] = val;        else nums[val-1] = -nums[val-1];    }    ans[1] ^= ans[0];    return ans;}

08 小结

算法专题目前已日更超过四个月,算法题文章147+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

转载于:https://www.cnblogs.com/xiaochuan94/p/10549573.html

你可能感兴趣的文章
C#学习笔记(七):智能编译器
查看>>
Openflow协议规范
查看>>
struts2支持的结果处理类型
查看>>
11.2.3 Redis的启动停止
查看>>
如何验证cname,MX,spf记录是否生效?
查看>>
Centos系统mysql 忘记root用户的密码
查看>>
uva:10700 - Camel trading(贪婪)
查看>>
开启CURL扩展,让服务器支持PHP curl函数(远程采集)
查看>>
随笔1
查看>>
OpenStack Summit Paris 会议记录 - 11-05-2014
查看>>
asp.net 的page 基类页面 做一些判断 可以定义一个基类页面 继承Page类 然后重写OnPreLoad事件...
查看>>
解析Javascript事件冒泡机制
查看>>
linux 下一个 jira-6.3.6 组态 皴 翻译 迁移数据库
查看>>
frequentism-and-bayesianism-chs-iv
查看>>
The Unique MST (判断是否存在多个最小生成树)
查看>>
ZOJ 2319 Beatuiful People(单调递增序列的变形)
查看>>
大型网站技术架构(1)【转】
查看>>
centos7 install 安装mysql
查看>>
C++11在时空性能方面的改进
查看>>
Android ListView 单条刷新方法实践及原理解析
查看>>