找出数组中重复的数字。
在一个长度为 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;
};