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

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

相关推荐
努力的小帅39 分钟前
C++_红黑树树
开发语言·数据结构·c++·学习·算法·红黑树
CoovallyAIHub1 小时前
YotoR模型:Transformer与YOLO新结合,打造“又快又准”的目标检测模型
深度学习·算法·计算机视觉
逐花归海.1 小时前
『 C++ 入门到放弃 』- 哈希表
数据结构·c++·程序人生·哈希算法·散列表
孟大本事要学习1 小时前
算法第29天|动态规划dp2:不同路径、不同路径Ⅱ、整数拆分、不同的二叉搜索树
算法·动态规划
ezl1fe1 小时前
RAG 每日一技(九):你的RAG是“人工智障”还是“真智能”?聊聊RAG的评估
后端·算法
এ᭄画画的北北2 小时前
力扣-51.N皇后
算法·leetcode
qqxhb2 小时前
零基础数据结构与算法——第六章:算法设计范式与高级主题-设计技巧(上)
java·数据结构·算法·分解·空间换时间·时空平衡
1白天的黑夜12 小时前
前缀和-974.和可被k整除的子数组-力扣(LeetCode)
c++·leetcode·前缀和
2 小时前
LeetCode Hot 100 搜索二维矩阵
算法·leetcode·矩阵
xiaofann_2 小时前
【数据结构】用堆实现排序
数据结构