LeetCode 287. 寻找重复数(不修改数组 + O(1) 空间)

287. 寻找重复数

📌 题目描述

给定一个包含 n + 1 个整数的数组 nums,其所有数字都在区间 [1, n] 范围内(包含 1 和 n)。由于数组中包含 n + 1 个数,而数的取值范围只有 n 个,因此至少存在一个重复的数

请你返回这个唯一重复的数

❗ 限制条件

  • 不能修改数组(不能排序或哈希)

  • 只使用常量级空间(不能使用额外的集合)

  • 时间复杂度 < O(n²) ,理想为 O(n)

🧠 解法:快慢指针(Floyd 判圈算法)

我们将数组视为一个链表,数组的下标是链表的节点编号,元素值是链表的"指针"------即跳转的位置。

复制代码
例如:nums = [1, 3, 4, 2, 2]
可看作链表:
0 → 1 → 3 → 2 → 4 → 2 → 4 → 2 → ...

重复数字造成了"环",问题转换为:**找环的入口**

✅ Floyd 算法分两步:

第一步:快慢指针相遇(找环中某个点)
python 复制代码
slow = nums[0]
fast = nums[0]

# 快走两步,慢走一步
while True:
    slow = nums[slow]
    fast = nums[nums[fast]]
    if slow == fast:
        break

第二步:从起点再来一次,寻找环的起点(即重复数字)

python 复制代码
slow = nums[0]
while slow != fast:
    slow = nums[slow]
    fast = nums[fast]

此时 slow == fast 即为环的入口,也就是重复数字。

✅ 完整代码

python 复制代码
class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        # 第一步:快慢指针相遇
        slow = nums[0]
        fast = nums[0]
        while True:
            slow = nums[slow]
            fast = nums[nums[fast]]
            if slow == fast:
                break

        # 第二步:找环的入口
        slow = nums[0]
        while slow != fast:
            slow = nums[slow]
            fast = nums[fast]

        return slow

⏱️ 时间复杂度与空间复杂度分析

指标 说明
⏱️ 时间复杂度 O(n),快慢指针最多跑两轮链表
💾 空间复杂度 O(1),只用了几个变量

📌 总结

  • 不能修改原数组 ➜ 排除排序、计数等解法

  • 要求 O(1) 空间 ➜ 排除哈希表

  • 使用链表快慢指针 ➜ 经典技巧,空间压缩到极致!

相关推荐
代码不停12 分钟前
BFS解决floodfill算法题目练习
算法·宽度优先
上弦月-编程19 分钟前
C语言指针从入门到实战
java·jvm·算法
WL_Aurora19 分钟前
Python 算法基础篇之树和二叉树
python·算法
txzrxz21 分钟前
关于前缀和
算法·动态规划·图论
杨连江23 分钟前
载流子矩阵限域束缚实现常温常压超导的理论与结构设计
算法
做cv的小昊31 分钟前
【TJU】研究生应用统计学课程笔记(6)——第二章 参数估计(2.4 区间估计)
人工智能·笔记·线性代数·算法·机器学习·数学建模·概率论
普贤莲花38 分钟前
【2026年第18周---写于20260501】---舍得
程序人生·算法·leetcode
2zcode38 分钟前
基于深度学习的口腔疾病图像识别系统(UI界面+改进算法+数据集+训练代码)
人工智能·深度学习·算法
Sarvartha1 小时前
N 个字符串最长公共子序列(LCS)求解问题
数据结构·算法
一切皆是因缘际会1 小时前
下一代 AI 架构:基于记忆演化与单向投影的安全智能系统
大数据·人工智能·深度学习·算法·安全·架构