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

LeetCode 442--陣列中重複的資料

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

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

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

示例:

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

輸出:
[2,3]

 不符合題意確實最好想的辦法是採用一個HashMap。類似於統計詞頻。雖然最後能通過OJ。。但是確很耗時間,大約100ms。

class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        ArrayList<Integer> res = new ArrayList<>();
        HashMap<Integer,Integer> hash = new HashMap<>();
        
        //先迴圈一邊寫一次HashMap
        
        for(int i = 0 ; i < nums.length ; i ++){
            if(!hash.containsKey(nums[i]))
                hash.put(nums[i],1);
            else
                hash.put(nums[i],hash.get(nums[i]) + 1);    
        }
        
        //遍歷一邊hash表
        for(int key : hash.keySet()){
            if(hash.get(key) == 2)
                res.add(key);
        }
        
        return res;
        
    }
}

第二種操作就比較有技巧了,這種操作的核心思想在於我遍歷這個陣列,由於題上已經說了每個數的取值不會超過陣列的長度。因此陣列中每個數的資料都可以當作下標來索引到對應的地方。

For example:nums = [2,3,5,3,2,4,6,4] 遍歷一個數的時候,找到對應下標為為(2-1 = 1)的位置,此時nums[1] = 3,為正數,我們此時把3變成負數,用來標記2已經出現過了,下次如果再遇到2.比如遍歷到第五個位置,我們找到對應下標為[2 -1 = 1],此時我們發現nums[1]  = -3.說明已經出現過了。返回這個數。

 對應的code如下。

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

        }
        return res;
    }
}

 

 歡迎討論!