当前位置: 首页 > news >正文

LeetCode 287. 寻找重复数:从直觉到 Floyd 判圈的完整推导

一、题目描述

给定一个长度为n + 1的数组nums,其中:

  • 所有数字都在[1, n]范围内

  • 只有一个重复的数字(但可能重复多次)

请找出这个重复的数字。

⚠️限制条件(重点)

  • ❌ 不能修改原数组

  • ✅ 只使用O(1)​ 额外空间

示例:

输入:nums = [1,3,4,2,2] 输出:2 输入:nums = [3,1,3,4,2] 输出:3

二、为什么这题“看起来简单但很难”

如果你允许修改数组,这题很简单:

方法

思路

问题

排序

相邻比较

修改数组 ❌

HashSet

记录出现次数

额外空间 ❌

但题目明确要求:

不能改数组 + O(1) 空间

👉 于是我们必须把“数组本身”当成某种结构来推理


三、核心洞察:把数组看成「链表」

1️⃣ 关键抽象

数组下标:0 ~ n

数组取值:1 ~ n

我们可以把数组理解成一个映射函数

f(i) = nums[i]

从任意位置i出发,不断执行:

i → nums[i] → nums[nums[i]] → ...

👉 这本质上是一条链表路径


2️⃣ 为什么一定有环?

  • 节点数:n + 1

  • 值域:1 ~ n(没有 0)

➡️必然存在某个节点被指向多次

➡️必然形成环

而:

环的入口,就是那个重复的数字


四、Floyd 判圈算法(快慢指针)

这正是Linked List Cycle II​ 的翻版。

Step 1:找相遇点(快慢指针)

slow = nums[slow] fast = nums[nums[fast]]

最终它们一定在环内某点相遇


Step 2:找环的入口(重复数)

将其中一个指针重置到起点:

slow = 0

然后同步前进:

slow = nums[slow] fast = nums[fast]

再次相遇的位置,就是重复的数字


五、结合例子理解(非常关键)

nums = [1,3,4,2,2]为例:

索引路径:

0 → 1 → 3 → 2 → 4 → 2 → 4 → ...

结构如下:

0 → 1 → 3 → 2 ↓ 4
  • 环:2 → 4 → 2

  • 环的入口:2

  • ✅ 答案就是2


六、为什么这个方法一定正确?

阶段

目的

快慢指针相遇

证明存在环

重置一个指针

对齐起点与环入口距离

同步移动

数学上必然在入口相遇

这是一个严格可证明​ 的算法,不是“玄学”。


七、Java 实现(面试标准版)

class Solution { public int findDuplicate(int[] nums) { int slow = 0, fast = 0; // Step 1: 找到相遇点 do { slow = nums[slow]; fast = nums[nums[fast]]; } while (slow != fast); // Step 2: 找到环的入口(重复数) slow = 0; while (slow != fast) { slow = nums[slow]; fast = nums[fast]; } return slow; } }

八、复杂度分析

指标

数值

时间复杂度

O(n)

空间复杂度

O(1) ✅

是否修改数组

完全满足题目所有限制。


九、易错点总结(面试高频)

不要尝试排序 / HashMap / 计数数组

错误思路

原因

排序

修改数组

HashSet

额外空间

二分

可行但不是最优直观解

面试加分点

“这题本质是一个隐式链表 + Floyd 判圈问题。”


十、总结一句话

解法

特点

暴力 / 排序

❌ 不满足限制

哈希表

❌ 空间超限

Floyd 判圈

✅ 最优解

📌记忆口诀

数组当链表,快慢找相遇,重置再同步,入口即答案

http://www.jsqmd.com/news/1090649/

相关文章:

  • Python的__init_subclass__验证
  • 3分钟掌握B站缓存视频转换:m4s转MP4完整教程
  • 自动驾驶极极极极简发展史
  • 操作系统内存管理
  • 猫抓:如何解决网页视频无法下载的三大难题?
  • AI写专著全流程解析:AI工具如何助力快速完成20万字专著创作?
  • 【共创季稿事节】鸿蒙原生 ArkTS 布局方式之 @Extend 扩展方法深度解析
  • 哈夫曼编码和香农-范诺编码的性能对比 P124302171陈新阳
  • android compose TimePicker 时间选择器 使用
  • (一)Kotlin—基础语法
  • MySQL 查询优化的执行计划分析
  • KingbaseES数据库空间管理实战:精准掌控库与表的数据体量
  • 欺诈检测化技术行为分析模型与实时规则引擎
  • 技术桥接的抽象实现分离设计
  • ShiroExploit v2.51实战解析:Apache Shiro反序列化漏洞自动化利用与防御
  • 竞争监测化技术竞品功能对比与市场情报收集
  • TestDisk终极指南:5步快速恢复丢失分区与数据
  • Paperclip - 多Agent编排管理平台详细介绍
  • 如何用Groove音乐播放器打造你的终极音乐管理系统
  • 想掌握手机号测吉凶技巧,913.com.cn平台详细解析
  • Bitget发布Web3人才报告:54%求职者受困「经验门槛」,AI与区块链融合成最热职业方向
  • 深度掌控AMD Ryzen:专业级SMU调试工具完全指南
  • Hermes - AI Agent 运行时框架详细介绍
  • ORCAD中连接符的使用
  • 别再熬夜写论文了!6款AI写作辅助平台,一键秒创超长篇幅内容!
  • 原型驱动可解释AI:让模型决策像人类一样可追溯
  • 如何高效配置ADBKeyBoard:3种实战方案深度解析Android自动化输入工具
  • 开源WPS AI插件察元AI文档助手:能力策略:风险类别与默认命名空间
  • 程序启动过程
  • 零基础 | Claude Code 工具推荐 claude-code-setup 和 Find Skills