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) 空间 ➜ 排除哈希表

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

相关推荐
KingRumn1 天前
Linux信号之标准信号与实时信号
linux·算法
源代码•宸1 天前
Leetcode—620. 有趣的电影&&Q3. 有趣的电影【简单】
数据库·后端·mysql·算法·leetcode·职场和发展
2301_800256111 天前
地理空间数据库中的CPU 和 I/O 开销
数据库·算法·oracle
一个不知名程序员www1 天前
算法学习入门---结构体和类(C++)
c++·算法
XFF不秃头1 天前
力扣刷题笔记-旋转图像
c++·笔记·算法·leetcode
王老师青少年编程1 天前
csp信奥赛C++标准模板库STL案例应用3
c++·算法·stl·csp·信奥赛·lower_bound·标准模版库
有为少年1 天前
Welford 算法 | 优雅地计算海量数据的均值与方差
人工智能·深度学习·神经网络·学习·算法·机器学习·均值算法
Ven%1 天前
从单轮问答到连贯对话:RAG多轮对话技术详解
人工智能·python·深度学习·神经网络·算法
山楂树の1 天前
爬楼梯(动态规划)
算法·动态规划