645. 错误的集合

一、题目

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

给定一个数组 nums 代表了集合 S 发生错误后的结果。你的任务是首先寻找到重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

示例 1:

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

注意:

  1. 给定数组的长度范围是 [2, 10000]。
  2. 给定的数组是无序的。

二、题解

法1

  • 嵌套for遍历找到错误值
  • 由于发生错误前后只有,数组只有正确值变成了错误值,其余的数不变,因此其余数的总和发生错误前后也相等
    • 正确总和 - 正确值 = 错误总和 - 错误值
    • 正确值 = 正确总和 - (错误总和 - 错误值)
    • 由于是从1开始连续的数,用等差数列求和——(最小值+最大值)*个数 / 2
      • 由于是从1开始连续的数,最小值为1
      • 由于是从1开始连续的无序数组,数组多长,最大值就应该有多大
class Solution {
    public int[] findErrorNums(int[] nums) {

        int wrongNum = 0;
        int rightNum = 0;
        int rightSum = 0;
        int wrongSum = 0;

        for (int i = 0; i < nums.length; i++) {
            for (int j = i+1; j < nums.length; j++) {
                if (nums[i]==nums[j]) {
                    wrongNum = nums[i];
                }
            }
            wrongSum+=nums[i];
        }

        rightSum = (1 + nums.length) * nums.length/ 2;
        rightNum = rightSum - (wrongSum - wrongNum);

        return new int[]{wrongNum,rightNum};
    }
}
  • 时间复杂度O(n^2)

  • 空间复杂度O(1),使用恒定的额外空间。

  • 执行用时:715 ms, 在所有 Java 提交中击败了5.62%的用户

  • 内存消耗:39.9 MB, 在所有 Java 提交中击败了90.52%的用户

法2

  • 创建一个存储数组,用于统计出现两次的数——错误值
  • 由于给定数组是从1开始的连续数组
    • 所以给定数组中每一个元素都可以作为存储数组的索引
    • 所以存储数组从1开始存数,存给定数组的n个数,所以存储数组长度应为n+1
  • 存储数组初始为0
    • 因此当同一个索引存入了相同的一个数,存储数组值+1,则那个数就是错误值
    • 由于正确值的缺失,因此以正确值为索引的那一个元素,不会存入数,仍然为初始值0
  • 再从索引1遍历一遍存储数组,值为0的那个数的索引就是正确值
class Solution {
    public int[] findErrorNums(int[] nums) {

        int rightNum = 0;
        int wrongNum = 0;

        int[] cnt = new int[nums.length+1];

        for (int i = 0; i < nums.length; i++) {
            if (cnt[nums[i]]!=0) {
                wrongNum = nums[i];
            }
            cnt[nums[i]]++;
        }

        for (int i = 1; i < cnt.length; i++) {
            if (cnt[i]==0) {
                rightNum = i;
            }
        }

        return new int[]{wrongNum,rightNum};
    }
}
  • 时间复杂度O(n)
  • 空间复杂度O(n)。
  • 执行用时:1 ms, 在所有 Java 提交中击败了100.00%的用户
  • 内存消耗:40.3 MB, 在所有 Java 提交中击败了53.50%的用户

法3

  • 参考方法——448.找到所有数组中消失的数字

    • 不使用额外空间,使用nums本身作为存储空间
    • 正数为出现次数为0的数,负数表示出现次数大于等于1的数
  • 例子[2, 3, 2]

  • 统计的数字 1 2 3
    nums的索引 0 1 2
    nums的元素 2 3 2
    第一轮 -3
    第二轮 -2
    第三轮 N<0 记录|-2|
    nums最终结果 2 -3 -2
    • 错误的数为记录的值
    • 正确的数为正数的索引+1——1
class Solution {
    public int[] findErrorNums(int[] nums) {

        int corNum = 0;
        int wroNum = 0;

        for (int i = 0; i < nums.length; i++) {
            if (nums[Math.abs(nums[i])-1]>0) {
                nums[Math.abs(nums[i])-1] *= -1;
            } else {
                wroNum = Math.abs(nums[i]);
            }
        }

        for (int i = 0; i < nums.length; i++) {
            if (nums[i]>0) {
                corNum = i+1;
            }
        }

        return new int[]{wroNum,corNum};
    }
}
  • 时间复杂度O(n)

  • 空间复杂度O(1)

  • 执行用时:3 ms, 在所有 Java 提交中击败了72.30%的用户

  • 内存消耗:39.6 MB, 在所有 Java 提交中击败了97.73%的用户

posted @ 2020-10-21 19:16  球球z  阅读(90)  评论(0)    收藏  举报