LeetCode hard 面试题 17.19.消失的两个数

题目描述:

给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?
以任意顺序返回这两个数字均可。

示例 1:

输入: [1]
输出: [2,3]

示例 2:

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

提示:

  • nums.length <= 30000

题解:

方法一:求和解法

先求的缺失的两个数的和sumTwo以及平均值temp,通过temp将数组分组,大于temp的一组,小于的一组。如果两个两个数不相等,则两个数一定位于不同的组中。
这样消失的两个数问题就转化为了17.04.消失的数字问题,在一个分组中可求得其中一个数a,另一个数即为sumTwo - a 。

class Solution {
    public int[] missingTwo(int[] nums) {
        int n = nums.length + 2;
        int sum = 0;

        for (int i = 0; i < nums.length; i++)//求数组中的数的和
            sum += nums[i];
        int sumTwo = ((1 + n) * n / 2) - sum;//缺失的两个数的和
        int temp = sumTwo / 2;

        sum = 0;
        for( int i = 0; i < nums.length; i++){
            if (nums[i] <= temp)
                sum += nums[i];
        }
        int firstNumber = ((1 + temp) * temp / 2) - sum;//缺失的其中一个数

        return  new int[]{firstNumber, sumTwo - firstNumber};
    }
}

方法二:分组异或解法

LeetCode easy 面试题17.04.消失的数字这题解法类似,都可通过异或思路解决。添加没有缺失的从1到N的所有整数,这样除了缺失的两个数,其余所有的数都出现过两次。
此时问题就和LeetCode medium 剑指 Offer 56 - Ⅰ数组中数字出现的次数一样了。

class Solution {
    public int[] missingTwo(int[] nums) {
        int ret = 0;
        int n = nums.length + 2;
        for (int num: nums)
            ret ^= num;
        for (int i = 1; i <= n; i++)//添加一次1,2,3...n序列与ret异或,
            ret ^= i;

        //找到ret二进制数中第几位是1
        int target = 1;//初始位0001
        //如果target第一个二进制位不为1,就将target左移一位位0010,
        //然后与ret相与,判断ret第二位是否为一.按此循环,
        //直到找到ret的第一个为1的二进制位
        while ((target & ret) == 0)
            target <<= 1;

        int firstNum = 0, secondNum = 0;
        for (int num: nums) {
            if ((num & target) == 0) {
                firstNum ^= num;
            } else{
                secondNum ^= num;
            }
        }
        for(int i = 1; i <= n; i++){
            if ((i & target) == 0)
                firstNum ^= i;
            else
                secondNum ^= i;
        }

        return new int[]{firstNum, secondNum};
    }
}

方法三:原地hash
参考文章:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/solution/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-by-leetcode/940638
www还是没看懂,先记录下吧

public int[] missingTwo(int[] nums) {
            int size = nums.length;
            int[] arr = new int[size + 3];
            arr[0] = arr[1] = arr[2] = -1;
            for (int i = 3; i < arr.length; i++) arr[i] = nums[i - 3];
            for (int i = 0; i < arr.length; i++) {
                while (i != arr[i] && arr[i] != -1) {
                    swap(arr, i, arr[i]);
                }
            }
            int[] res = new int[2];
            for (int i = 1; i < arr.length; i++) {
                if (arr[i] == -1) {
                    if (res[0] == 0) res[0] = i;
                    else res[1] = i;
                }
            }
            return res;
        }

        private void swap(int[] nums, int i, int j) {
            int t = nums[i];
            nums[i] = nums[j];
            nums[j] = t;
        }
上一篇:如何将本地代码上传到码云、如何找回误删的本地代码


下一篇:Mathematically Hard(小于n且与n互质的数的个数==欧拉函数,欧拉表)