555 字
3 分钟
寻找重复数

题目描述
给定一个包含 n + 1
个整数的数组 nums
,其数字都在 [1, n]
范围内(包括 1
和 n
),可知至少存在一个重复的整数。
假设 nums
只有 一个重复的整数 ,返回 这个重复的数 。
你设计的解决方案必须 不修改 数组 nums
且只用常量级 O(1)
的额外空间。
解题思路
- 链表环检测法:
- 将数组视为链表:索引为节点,值为下一节点索引
- 重复元素导致多指针指向同一节点形成环
- Floyd判圈算法:
- 快慢指针从起点出发,快指针两步,慢指针一步
- 相遇后重置快指针,同速移动再遇点为环入口
- 环入口即重复数:
- 环入口节点对应多个指针指向,即重复值
- 数学原理:
- 设环长为L,起点到入口a步,入口到相遇点b步
- 2(a+b) = a+b+kL → a = (k-1)L + (L-b)
关键洞察
- 数组映射链表:
- 索引→节点,值→next指针
- 重复值导致多入度形成环
- 环入口性质:
- 环入口节点即为重复数
- 非环入口重复不影响检测
- Floyd算法适用性:
- 完美匹配本题空间限制
- 脱离传统哈希表解法
- 边界保证:
- 值域[1,n]长度n+1确保必有环
- 不会出现越界指针
复杂度分析
指标 | 说明 |
---|---|
时间复杂度 | O(n):两轮指针遍历各O(n) |
空间复杂度 | O(1):仅需两个指针 |
代码实现
/** * @param {number[]} nums * @return {number} */var findDuplicate = function (nums) { let slow = 0, fast = 0; do { slow = nums[slow]; fast = nums[nums[fast]] } while (slow !== fast) slow = 0; while (slow !== fast) { slow = nums[slow]; fast = nums[fast] } return slow;};
实际应用场景
- 数据库审计:检测重复主键:主键值映射为数组索引`
- 网络协议分析:定位重复传输的数据包ID`
- 内存管理:检测重复内存地址分配`
- 生物信息学:基因序列中定位重复编码段`