寻找重复数

GitHub跳转原题关系图返回列表

把值视为 next 指针,Floyd 找环入口即为重复数。

OJ: leetcodecn

题目 ID: find-the-duplicate-number

难度:提高+/省选-

标签:快慢指针链表技巧

日期: 2026-07-29 13:04

题意

在 n+1 个元素(值域 [1,n])中找重复数,不修改数组,O(1) 空间。

思路

nums[i] 视为从 inums[i] 的 next 指针,数组构成一个有环链表(重复值导致两个节点指向同一后继)。Floyd 快慢指针找环入口即为重复数。

代码

cpp
#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    int findDuplicate(vector<int> &nums) {
        int slow = nums[0], fast = nums[0];
        do {
            slow = nums[slow];
            fast = nums[nums[fast]];
        } while (slow != fast);
        slow = nums[0];
        while (slow != fast) {
            slow = nums[slow];
            fast = nums[fast];
        }
        return slow;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<int> a(n);
    for (int &x : a)
        cin >> x;
    cout << Solution().findDuplicate(a) << '\n';
    return 0;
}
python
#!/usr/bin/env python3
from typing import List


class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        slow = 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


def main():
    n = int(input())
    a = list(map(int, input().split()))
    print(Solution().findDuplicate(a))


if __name__ == "__main__":
    main()

复杂度

  • 时间复杂度:O(n)O(n)
  • 空间复杂度:O(1)O(1)

总结

把数组值视为 next 指针是本题的关键映射。重复数意味着两个位置指向同一个后继,形成环。Floyd 找环入口的证明与链表环检测完全相同。