1.找出數組中重復的數字 ----《劍指Offer》題解(Java)


題目

給定一個長度為 n 的整數數組 nums,數組中所有的數字都在 0∼n−1 的范圍內。

數組中某些數字是重復的,但不知道有幾個數字重復了,也不知道每個數字重復了幾次。

請找出數組中任意一個重復的數字。

注意:如果某些數字不在 0∼n−1 的范圍內,或數組中不包含重復數字,則返回 -1;

樣例
給定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。

返回 2 或 3。

算法思路

找重復數字可以直接用HashMap來解決,但需要額外的空間。
本題可以只用O(1)的空間復雜度來實現,具體思路是:
由於數字范圍是[0, n-1],數組長度是n,因此可把數組當做是數字的槽位,依次將數字放到對應數組下標的位置去。
遍歷數組,將當前元素nums[i]放到它對應的數組下標的位置去,即swap(nums[i] , nums[nums[i]]),注意交換到位置i的數字也要繼續放到它相應的槽去,依次循環直到當前位置i放入了正確的數字,即nums[i] == i。
假如在將當前位置的元素放到正確位置的時候,發現該位置已經是正確的數字了,說明有重復,直接返回該數字即可。
需要注意,題目中“如果某些數字不在 0∼n−1 的范圍內,則返回 -1”,這是個坑,需要提前判斷,如果在遍歷數組中判斷則可能先找到重復元素,就退出,超出范圍的數還沒被判斷到。
算法的時間復雜度是O(n)

代碼實現

class Solution {
    public int duplicateInArray(int[] nums) {
        if (nums == null || nums.length == 0) return -1;
        int n = nums.length;
        //提前遍歷判斷"如果某些數字不在 0∼n−1 的范圍內,則返回 -1"
        for (int i=0; i<n; i++) { 
            if (!(nums[i] >= 0 && nums[i] < n)) return -1;
        }
        
        for (int i=0; i<n; i++) {
            //循環將當前位置的元素放到對應的槽去
            while (nums[i] != nums[nums[i]]) swap(nums, i, nums[i]); 
            
            //當前元素應該放到對應位置,但該位置的數字跟當前的一樣,即重復了
            if (nums[i] != i && nums[i] == nums[nums[i]]) return nums[i]; 
        }
        
        return -1;
    }
    
    //交換數組兩個元素
    private void swap(int[] nums, int i, int j) {
        nums[i] = nums[i] ^ nums[j];
        nums[j] = nums[i] ^ nums[j];
        nums[i] = nums[i] ^ nums[j];
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM