算法: 剑指 Offer 03. 数组中重复的数字
题目
要求: 找出数组中重复的数字。
题目描述:在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入: [2, 3, 1, 0, 2, 5, 3] 输出:2 或 3
限制:
2 <= n <= 100000
来源:力扣(LeetCode)链接:剑指 Offer 03. 数组中重复的数字
解题思路
方法一 : 排序数组
- 将输入的数组排序
- 从头到尾扫描排序后的数组,找出重复的数组
- Time: O(nlogn)
- Space: O(1)
方法二 : 哈希表
- 从头到尾按顺序扫描数组每个数组,每扫描一个数字的时候,都可以用O(1)的瞬间来判断哈希是否包含此数字。
- 如果哈希表没有这数字,则加入哈希表。如果有,则找到了重复的数字。
- Time:O(1)
- Space: O(n)
方法三: 比较 - 交换
- 判断i对应值与下标是否不相同,相同则下一个元素。不同则将值作为下标m,找到下标m对应的值。
- 判断m对应值与i对应的值是否相等,不相等则交换
- 直到当前i位置的值等于下标值
代码
/**
* @param {number[]} nums
* @return {number}
*/
/**
* 思路:
* 1. 判断i对应值与下标是否相同,相同则继续。不同则将值作为下标m,找到m对应的值。
* 2. 判断此时m下标对应值与i对应值是否相等,不相等则交换。
*
* Time: 尽管两重循环,但每个数字最多只要交换两次就能找到属于它自己的位置,总的Time: O(n)
* Space: 不需要分配额外空间, space: O(1)
*/
var findRepeatNumber = function(nums) {
let len = nums.length;
if(nums == null || len <= 0){
return -1;
}
for(let i = 0;i < len; ++i){
if(nums[i] < 0 || nums[i] > len - 1){
return false
}
}
const swap = (nums,index1,index2) => {
[nums[index1],nums[index2]] = [nums[index2],nums[index1]];
}
for(let i = 0; i < len; ++i){
while(nums[i] != i){
if(nums[i] == nums[nums[i]]){
// i.value = m.value
return nums[i];
}
swap(nums,i,nums[i]);
}
}
return nums[i];
};