LeetCode 645. Set Mismatch

You have a set of integers s, which originally contains all the numbers from 1 to n. Unfortunately, due to some error, one of the numbers in s got duplicated to another number in the set, which results in repetition of one number and loss of another number.

You are given an integer array nums representing the data status of this set after the error.

Find the number that occurs twice and the number that is missing and return them in the form of an array.

Example 1:

Input: nums = [1,2,2,4]
Output: [2,3]

Example 2:

Input: nums = [1,1]
Output: [1,2]

Constraints:

  • 2 <= nums.length <= 104
  • 1 <= nums[i] <= 104

给了个长度为n的数组,里面包含了1-n的数字,其中有一个重复的和一个丢失的,要求这俩数字。

好像之前做过非常类似的,448,不过那道题里不知道丢失的数字有多少。LeetCode 448. Find All Numbers Disappeared in an Array_wenyq7的博客-CSDN博客

1. 排序 O(nlogn)

一个很直观的想法就是通过排序,然后check前后的数字是否一样,如果一样就说明是duplicated,如果不一样且相差不是1,那这俩数字中间的那个就是missing。需要先初始化这两个变量,初始化这里就很有技巧了,dupe可以随便初始化,因为总能找到,但miss需要初始化成1,which is第一个可能出现的数字。如果找到最后都没更新这个miss,那么有两种情况,一种情况就是1丢了,另一种情况就是最后一个数字丢了,通过初始化为1可以cover第一种情况,最后一种情况需要通过判断最后一个元素是不是和n相等来决定,如果不相等的话那miss就是它。

test的时候刷新了一下页面结果ui换了,于是没有runtime %了。

class Solution {
    public int[] findErrorNums(int[] nums) {
        Arrays.sort(nums);
        int miss = 1;
        int dupe = -1;
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] == nums[i - 1]) {
                dupe = nums[i];
            } else if (nums[i] != nums[i - 1] + 1) {
                miss = nums[i - 1] + 1;
            }
        }
        int[] result = new int[2];
        result[0] = dupe;
        result[1] = nums.length != nums[nums.length - 1] ? nums.length : miss;
        return result;
    }
}

2. extra array with index. O(n) + O(n)

新建一个数组,用它的下标表示这个数字,新建了n + 1长度的数组这样就不用match到0-index了。

Runtime4 ms Beats 82.63%  Memory54.3 MB Beats 73.83%

class Solution {
    public int[] findErrorNums(int[] nums) {
        boolean[] found = new boolean[nums.length + 1];
        int[] result = new int[2];
        for (int i = 0; i < nums.length; i++) {
            if (found[nums[i]]) {
                result[0] = nums[i];
            }
            found[nums[i]] = true;
        }
        for (int i = 1; i < nums.length + 1; i++) {
            if (!found[i]) {
                result[1] = i;
            }
        }
        return result;
    }
}

3. 用当前array的index表示是否出现过,类似448。O(n) + O(1)

就跟448一个思路,用当前这个array的index记录是否出现过。如果出现过就变成负的,如果已经是负的说明就重复了,最后看一遍正的那个就是丢失的。然后写代码的时候也是一堆小坑没注意的就踩进去了……最好是先把index求出来,不然容易和i搞混,以及还有1-index和0-index的转换。以及注意一定要用绝对值。就,虽然思路很简单但代码细节太多了……

Runtime12 ms Beat 50.38% Memory54.5 MB Beats 66.39%

class Solution {
    public int[] findErrorNums(int[] nums) {
        int[] result = new int[2];
        for (int i = 0; i < nums.length; i++) {
            int index = Math.abs(nums[i]) - 1;
            if (nums[index] < 0) {
                result[0] = Math.abs(nums[i]);
            } else {
                nums[index] = -nums[index];
            }
        }
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > 0) {
                result[1] = i + 1;
            }
        }
        return result;
    }
}

solutions里也给出了用map做,就记录每个元素出现的次数。感觉好像没必要就改成了set,然后发现,这不就是题目吗……感觉这是个无效的做法……

class Solution {
    public int[] findErrorNums(int[] nums) {
        Set<Integer> set = new HashSet<>();
        int miss = 1;
        int dupe = -1;
        for (int i = 0; i < nums.length; i++) {
            if (!set.contains(nums[i])) {
                set.add(nums[i]);
            } else {
                dupe = nums[i];
            }
        }
        for (int i = 0; i < nums.length; i++) {
            if (!set.contains(i + 1)) {
                miss = i + 1;
            }
        }
        int[] result = new int[2];
        result[0] = dupe;
        result[1] = miss;
        return result;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值