找出數組中重複的數字。
在一個長度爲 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;
};