100.寻找重复数

5 阅读1分钟

题目链接

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1n),可知至少存在一个重复的整数。

假设 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)