1. 程式人生 > >[LeetCode] Find All Numbers Disappeared in an Array 找出陣列中所有消失的數字

[LeetCode] Find All Numbers Disappeared in an Array 找出陣列中所有消失的數字

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]

這道題讓我們找出陣列中所有消失的數,跟之前那道Find All Duplicates in an Array極其類似,那道題讓找出所有重複的數字,這道題讓找不存在的數,這類問題的一個重要條件就是1 ≤ a[i] ≤ n (n = size of array),不然很難在O(1)空間和O(n)時間內完成。三種解法也跟之前題目的解法極其類似。首先來看第一種解法,這種解法的思路路是,對於每個數字nums[i],如果其對應的nums[nums[i] - 1]是正數,我們就賦值為其相反數,如果已經是負數了,就不變了,那麼最後我們只要把留下的整數對應的位置加入結果res中即可,參見程式碼如下:

解法一:

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        vector<int> res;
        for (int i = 0; i < nums.size(); ++i) {
            int idx = abs(nums[i]) - 1;
            nums[idx] = (nums[idx] > 0) ? -nums[idx] : nums[idx];
        }
        
for (int i = 0; i < nums.size(); ++i) { if (nums[i] > 0) { res.push_back(i + 1); } } return res; } };

第二種方法是將nums[i]置換到其對應的位置nums[nums[i]-1]上去,比如對於沒有缺失項的正確的順序應該是[1, 2, 3, 4, 5, 6, 7, 8],而我們現在卻是[4,3,2,7,8,2,3,1],我們需要把數字移動到正確的位置上去,比如第一個4就應該和7先交換個位置,以此類推,最後得到的順序應該是[1, 2, 3, 4, 3, 2, 7, 8],我們最後在對應位置檢驗,如果nums[i]和i+1不等,那麼我們將i+1存入結果res中即可,參見程式碼如下:

解法二:

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

下面這種方法是在nums[nums[i]-1]位置累加陣列長度n,注意nums[i]-1有可能越界,所以我們需要對n取餘,最後要找出缺失的數只需要看nums[i]的值是否小於等於n即可,最後遍歷完nums[i]陣列為[12, 19, 18, 15, 8, 2, 11, 9],我們發現有兩個數字8和2小於等於n,那麼就可以通過i+1來得到正確的結果5和6了,參見程式碼如下:

解法三:

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        vector<int> res;
        int n = nums.size();
        for (int i = 0; i < n; ++i) {
            nums[(nums[i] - 1) % n] += n;            
        }
        for (int i = 0; i < n; ++i) {
            if (nums[i] <= n) {
                res.push_back(i + 1);
            }
        }
        return res;
    }
};

類似題目:

參考資料: