LeetCode [448. Find All Numbers Disappeared in an Array] 难度[easy]

题目

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements of [1, n] inclusive that do not appear in this array.

Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.

Example:

Input:
[4,3,2,7,8,2,3,1]

Output:
[5,6]

解题思路

题目大意如下:给定一个整型数组,数组元素的大小都在 1 到 n 之间,其中 n 为数组大小。元素可能出现一次或者两次,现在希望你能找出不属于该数组,但大小为[1,n]的元素,要求你的算法不需要使用额外的空间,并且时间复杂度为 O(n) 。

题目的难点主要在于限定你设计的算法空间复杂度为 O(1), 时间复杂度为 O(n)。一开始自己直观的想法就是先建立一个大小为 n 的布尔型数组,初始化为false,然后遍历一遍输入数组,将出现的元素对应的布尔值修改为true,最后只需再遍历一遍布尔型数组,布尔值为false的数组下标即为体重所求元素。虽然该算法的时间复杂度为 O(n), 但空间复杂度也为 O(n), 显然不满足题意。

于是改变思路,既然不能使用额外空间,而且不可能只遍历一遍就可得到答案(至少需要两次循环,每次循环都能得到一定量的信息),那么原数组肯定需要发生一些改变来存储第一次遍历后得到的信息。沿着这个思路,不难想出正确的算法,其中之一,如下所述:第一次循环将数组中元素作为下标对应的元素值变为负数,第二次循环判断元素值是否大于 0 , 大于 0 的话,说明其下标即为缺失值(在第一次循环中已经将出现过元素作为下标对应的元素值变为负数了,好像有点绕口 ORZ ,待会看看代码就应该很好理解了)。该算法空间复杂度为 O(1), 时间复杂度为 O(n), 满足题意。

参考代码

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        int len = nums.size();
        for(int i=0; i<len; i++) {
            int m = abs(nums[i])-1; // index start from 0
            nums[m] = nums[m]>0 ? -nums[m] : nums[m];
        }
        vector<int> res;
        for(int i = 0; i<len; i++) {
            if(nums[i] > 0) res.push_back(i+1);
        }
        return res;
    }
};
    原文作者:腾古
    原文地址: https://www.jianshu.com/p/c45acb6206e1
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞