[每日一题] 面试题 消失的两个数字

202 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

消失的两个数字

给定一个数组,包含从1N所有的整数,但其中缺了两个数字。 给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。

你能在O(N)时间内只用O(1)的空间找到它们吗? 你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?

示例 1:

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

示例 2:

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

思路

一共有n个数,我们缺少了两个数
形如:

1 0 0 2 3 4 5 6

这里的 0 代表的是 缺少的数

如何找到这两个缺少的数呢?

我的做法是排序!

但是一般的排序达不到这个要求

我们需要考虑一种O(n)的排序

当你读到这里,肯定会说,不可能,时间复杂度最低的排序算法是O(nlogn)

但是,我们的数据特殊一些

就导致了不一样的结构

下面我们来看看我的排序做法

这种做法利用的值域特别小的特点

假设当前的0,我们给他添加到末尾

然后我们就得到了这样一个数列

3 1 2 5 7 0 0

此时我们首先对第一个数进行操作

发现他并不等于他本身,于是我们做一次交换操作

2 1 3 5 7 0 0 // 交换 3到3的下标位置

然后,我们继续处理第一个数,当前为2

1 2 3 5 7 0 0 // 交换 2到2的下标位置

第一个数交换完毕,第二个数和第三个数也排好序了

然后,我们 对第四个数进行操作

1 2 3 7 5 0 0 // 同理交换

然后,对第四个数,交换到第七个位置

1 2 3 0 5 0 7 // 同理交换

此时,我们的数组就被神奇的交换好了!

也找出来了两个缺少的数,可能有的人就有疑问,为什么一定保证可以排好序呢?

不会出现这种情况吗?

1 0 3 2

走过了这个数,但是 0 却留着了前面

请注意,这里,若是当前这个数是存在的,总会被交换到对应位置

就可以一步一步的把0逼到对应没有的位置

也可以说,这是一种哈希吧。

代码

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) {
        vector<int> res;
        nums.push_back(0), nums.push_back(0);
        for (int i = 1; i <= nums.size(); i ++) 
            while (nums[i-1] != i && nums[i-1]) 
                swap(nums[i-1], nums[nums[i-1]-1]);
        for (int i = 1; i <= nums.size(); i ++)
            if (i != nums[i-1]) res.push_back(i);
        return res;
    }
};