1. 程式人生 > >[LeetCode] Find All Duplicates in an Array 找出陣列中所有重複項

[LeetCode] Find All Duplicates in an Array 找出陣列中所有重複項

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

Find all the elements that appear twice in this array.

Could you do it without extra space and in O(n) runtime?

Example:

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

Output:
[2,3]
這道題給了我們一個數組,陣列中的數字可能出現一次或兩次,讓我們找出所有出現兩次的數字,由於之前做過一道類似的題目
Find the Duplicate Number
,所以不是完全無從下手。這類問題的一個重要條件就是1 ≤ a[i] ≤ n (n = size of array),不然很難在O(1)空間和O(n)時間內完成。首先來看一種正負替換的方法,這類問題的核心是就是找nums[i]和nums[nums[i] - 1]的關係,我們的做法是,對於每個nums[i],我們將其對應的nums[nums[i] - 1]取相反數,如果其已經是負數了,說明之前存在過,我們將其加入結果res中即可,參見程式碼如下:

解法一:

class Solution {
public:
    vector
<int> findDuplicates(vector<int>& nums) { vector<int> res; for (int i = 0; i < nums.size(); ++i) { int idx = abs(nums[i]) - 1; if (nums[idx] < 0) res.push_back(idx + 1); nums[idx] = -nums[idx]; } 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不等,那麼我們將nums[i]存入結果res中即可,參見程式碼如下:

解法二:

class Solution {
public:
    vector<int> findDuplicates(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(nums[i]);
        }
        return res;
    }
};

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

解法三:

class Solution {
public:
    vector<int> findDuplicates(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] > 2 * n) res.push_back(i + 1);
        }
        return res;
    }
};

類似題目:

參考資料: