给定一个包含
n + 1
个整数的数组nums
,其数字都在[1, n]
范围内(包括1
和n
),可知至少存在一个重复的整数。假设
nums
只有 一个重复的整数 ,返回 这个重复的数 。你设计的解决方案必须 不修改 数组
nums
且只用常量级O(1)
的额外空间。
解法 快慢针
思路
最简单的思路就是将数字放在对应的 index
上,如果出现 nums[index] === index
的情况,那么说明找到了重复的数字,但是题目不允许修改数组,所以需要思考别的解法。
我们可以借鉴当时判断链表环形入口的方法,我们把数组看成一个链表,其中值表示跳转目标。因为数组长度是 n+1,数字范围是 1~n,必定有至少一个数字重复,等同于链表中一定有个节点被多次指向,也就是环。由于有重复,一定存在一个环。快慢针判圈算法可以在线性时间内找出这个环的入口,也就是那个重复的数字。
代码
function findDuplicate(nums: number[]): number {
// Step 1: 找到相遇点
let slow = nums[0];
let fast = nums[0];
do {
slow = nums[slow];
fast = nums[nums[fast]];
} while (slow !== fast);
// Step 2: 找入口(重复数字)
slow = nums[0];
while (slow !== fast) {
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
时空复杂度
时间复杂度:O(n)
空间复杂度:O(1)