【劍指 Offer 03】數組中重複的數字

找出數組中重複的數字。
在一個長度爲 n 的數組 nums 裏的所有數字都在 0~n-1 的範圍內。數組中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出數組中任意一個重複的數字。

示例 1:

輸入:
[2, 3, 1, 0, 2, 5, 3]
輸出:2 或 3 

限制:
2 <= n <= 100000

思路:

  • 一個簡單的方法就是先排序,然後在排序數組中找就比較簡單了。排序算法+從頭掃描,這個算法的時間複雜度是O(nlogn)
  • 另一種方法是,創建一個hash表,用來存放數據,每掃描一個數字,就可以判斷hash表裏是否有該數字,沒有就放進hash裏,有的話就返回。這樣的算法時間和空間複雜度都是O(n)
  • 第三種方法:
    • 我們注意到,數組裏的元素都是0~n-1範圍內的,如果這n個元素都不重複,那麼排序之後,數字i將會出現在下標i這個位置上。因爲數組裏有重複的數字,會導致某些位置上有超過一個的數字,有些則沒有。
    • 於是我們從頭到尾開始掃描這個數組
    • 當我們掃描到第i個值時,先判斷第i個數字m是否等於i,如果等於i,繼續掃描,如果不等於i,就讓數字m和第m個數值比較,如果相等,那就找到一個重複數字;如果不相等,那就把第i個數字m和第m個數字交換位置,讓數字m在第m個位置,然後重新比較,交換。直到發現重複數字。
const findRepeatNumber = (nums: number[]): number => {
    const res = [];
    const n = nums.length;
    // 判斷數組不爲空,且數組的長度等於給出的長度
    if(!nums.length) return -1;
    
    // 判斷數組內的每一個數字都在0~n-1的範圍內
    for(let i = 0; i < n; ++i) {
        if(nums[i] < 0 || nums[i] > n -1 ) {
            return -1;
        }
    }
    
    //掃描,比較和交換
    for(let i = 0; i < n; ++i) {
        while(nums[i] !== i) {
            if(nums[i] === nums[nums[i]]) {
                res.push(nums[i]);
                return res[0];
            }else{
                let temp = nums[i];
                nums[i] = nums[temp];
                nums[temp] = temp;
            }
        }
    }
    return -1;
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章