555 字
3 分钟
寻找重复数

题目描述#

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

假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

解题思路#

  1. 链表环检测法
    • 将数组视为链表:索引为节点,值为下一节点索引
    • 重复元素导致多指针指向同一节点形成环
  2. Floyd判圈算法
    • 快慢指针从起点出发,快指针两步,慢指针一步
    • 相遇后重置快指针,同速移动再遇点为环入口
  3. 环入口即重复数
    • 环入口节点对应多个指针指向,即重复值
  4. 数学原理
    • 设环长为L,起点到入口a步,入口到相遇点b步
    • 2(a+b) = a+b+kL → a = (k-1)L + (L-b)

关键洞察#

  1. 数组映射链表
    • 索引→节点,值→next指针
    • 重复值导致多入度形成环
  2. 环入口性质
    • 环入口节点即为重复数
    • 非环入口重复不影响检测
  3. Floyd算法适用性
    • 完美匹配本题空间限制
    • 脱离传统哈希表解法
  4. 边界保证
    • 值域[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;
};

实际应用场景#

  1. 数据库审计:检测重复主键:主键值映射为数组索引`
  2. 网络协议分析:定位重复传输的数据包ID`
  3. 内存管理:检测重复内存地址分配`
  4. 生物信息学:基因序列中定位重复编码段`

相似题目#

寻找重复数
https://website-truelovings-projects.vercel.app/posts/algorithms/寻找重复数/
作者
欢迎来到StarSky的网站!
发布于
2025-08-18
许可协议
CC BY-NC-SA 4.0