数组中重复的数字
- 题源:《剑指 Offer: 面试题 3》P39
- 在线:牛客网
题目
在一个长度为 n 的数组里的所有数字都在 0 ~ n-1 的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
示例:
输入:[2,3,1,0,2,5,3]
输出: 2 或者 3
思路
- 法一:先排序再用快慢指针找重复,但时间复杂度为 O(nlogn)
- 法二:HashTable 统计次数,但需要 O(n) 的辅助空间
- 法三:将元素下标和元素值交换直至相等,当
nums[nums[i]] === nums[i]
时返回该值即可
代码实现
function duplicate(nums) {
if (nums.length < 1) return;
for (let i = 0; i < nums.length; i++) {
while (nums[i] !== i) {
if (nums[nums[i]] === nums[i]) {
return nums[i];
}
let temp = nums[i];
nums[i] = nums[temp];
nums[temp] = temp;
}
}
}
思考能否将交换数组元素的部分写成如下几种形式:
let temp = nums[i];
nums[i] = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = nums[i] ^ nums[nums[i]];
nums[nums[i]] = nums[i] ^ nums[nums[i]];
nums[i] = nums[i] ^ nums[nums[i]];
[nums[nums[i]], nums[i]] = [nums[i], nums[nums[i]]];
复杂度
- 时间复杂度:O(n),虽然有两重循环,但每个数字最多只要交换两次就能找到属于它的位置。
- 空间复杂度:O(1)
拓展
在一个长度为 n+1 的数组里的所有数字都在 1 ~ n 的范围内。 所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字。但不能修改输入的数组。
示例:
输入:[2,3,5,4,3,2,6,7]
输出: 2 或者 3