【LeetCode】287. 寻找重复数

287 . 寻找重复数(中等)



方法 快慢指针

思路

  • 要解决这道题首先要理解如何将输入的数组看作为链表。对于数组 nums 中的数字范围在 [1, n],考虑两种情况:

    • 如果数组中没有重复的数字,以 [1, 3, 4, 2] 为例,将数组下标 n 和 nums[n] 建立映射关系f(n),即 n->f(n):0->1, 1->3, 2->4, 3->2 ,从下标 0 出发, 根据 f(n) 计算出一个值,以这个值为新的下标,依次类推,直到下标越界,这样产生了一个类似链表的序列:0->1->3->2->4->null

    • 如果数组中有重复的数字,以 [1, 3, 4, 2, 2] 为例, 其映射关系为 n->f(n):0->1, 1->3, 2->4, 3->2, 4->2 ,此时的"链表序列"为:0->1->3->2->4->2->... ,出现了循环2->4->2->4->...,如下图所示。

  • 因此,如果数组中出现重复的数字,那么就一定会产生多对一的映射,所以"链表序列"一定会有"环"。综上,数组中有重复的整数 <=> 数组中存在环,找到数组中重复的整数 <=> 找到链表中的环入口。

  • 针对这类型的题目,就需要使用快慢指针 ,慢指针走一步,快指针走两步,即 slow = nums[slow]fast = nums[nums[fast]]

  • 当 slow == fast 时,二者走到相遇点,记为 y 。将环的入口点记为 x ,链表起始点记为 h,设 链表起始点 h 到 x 的距离为 a, x 到 y 的距离为 b 。

  • 由于 "慢指针走过的距离是快指针的一半" ,则有 2 * (a + b) = a + b + (y 到 x 的距离) + b ,因此 y 到 x 的距离就等于 0 到 x 的距离 【注意:这里的 y 到 x 的距离可能走了很多圈】。此时再设置两个新指针,一个从 0 出发,一个从相遇点 y 出发,两个指针相遇的地方即为 环的入口点 x

代码

cpp 复制代码
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int slow = 0, fast = 0;
        // 找到相遇点
        do{
            slow = nums[slow];
            fast = nums[nums[fast]];
        }while(slow != fast);
        // 找到起始点
        // 起始点->环的起点 = 环的起点->相遇点
        int pre1 = 0, pre2 = slow;
        while(pre1 != pre2){
            pre1 = nums[pre1];
            pre2 = nums[pre2];
        }
        return pre1;
    }
};
相关推荐
NuyoahC1 小时前
笔试——Day46
c++·算法·笔试
Keying,,,,1 小时前
力扣hot100 | 图论 | 200. 岛屿数量、994. 腐烂的橘子、207. 课程表、208. 实现 Trie (前缀树)
算法·leetcode·图论
cwplh2 小时前
Codeforces1043 A至F 题解
算法
楼田莉子3 小时前
C++算法学习专题:滑动窗口
开发语言·数据结构·c++·学习·算法·leetcode
2501_924731113 小时前
智慧矿山误报率↓83%!陌讯多模态融合算法在矿用设备监控的落地优化
人工智能·算法·目标检测·视觉检测
zh_xuan4 小时前
LeeCode 40.组合总和II
c语言·数据结构·算法
都叫我大帅哥5 小时前
动态规划:从懵逼到装逼,一篇让你彻底搞懂DP的终极指南
java·算法
艾莉丝努力练剑5 小时前
《递归与迭代:从斐波那契到汉诺塔的算法精髓》
c语言·学习·算法
超级皮皮11 小时前
力扣热题之stack
算法·leetcode·职场和发展
weixin_4707403611 小时前
某算法的python执行汇编
汇编·python·算法