1. 程式人生 > >leetcode 442 陣列中重複的資料

leetcode 442 陣列中重複的資料

給定一個整數陣列 a,其中1 ≤ a[i] ≤ n (n為陣列長度), 其中有些元素出現兩次而其他元素出現一次

找到所有出現兩次的元素。

你可以不用到任何額外空間並在O(n)時間複雜度內解決這個問題嗎?

示例:

輸入:
[4,3,2,7,8,2,3,1]

輸出:
[2,3]

顯然,若可以使用額外空間,利用set的特性,判斷nums[i]是否存在set中,若存在則此數時重複的,記錄下來並將set中的該數刪除,若不存在則將其放入set中即可。

class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        List<Integer> res = new ArrayList<>();
        Set<Integer> set = new TreeSet<>();
        for(int num:nums){
            if(set.contains(num)){
                res.add(num);
                set.remove(num);
            }
            else{
                set.add(num);
            }
        }
        return res;
    }
}

另外,考慮不使用額外空間的演算法:

題目中沒有提到不能改變陣列元素的值,因此可以利用元素的正負性來進行技術。同時,因為1<=nums[i]<=n,所以每個元素都對應著另一個元素的索引,當我們遍歷到nums[i]時,將Math.abs(nums[i]-1)對應的元素取反,意味著nums[i]出現一次,如果nums[Math.abs(nums[i])-1]的值在取反之後變回正值,則說明在此之前nums[i]已經出現過了,將nums[i]記錄下來即可。

class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        for(int i=0;i<nums.length;i++){
            int tmp=Math.abs(nums[i]);
            nums[tmp-1]=-nums[tmp-1];
            if(nums[tmp-1]>0){
                res.add(tmp);
            }
        }
        return res;
    }
}