Skip to content
  • Linked List · Sheet 150

Find the Duplicate Number

LearnViaNotes @learnvianotes· 2 min read

Difficulty: Medium · LeetCode 287

Problem

Given an array of integers nums containing n + 1 integers where each integer is in range [1, n], find the duplicate number without modifying array in O(1) space.

Understanding the problem

Map array indices to values as an implicit linked list: index -> nums[index].

Intuition

Treat array as implicit linked list. The duplicate number represents the entrance to a cycle. Apply Floyd's Cycle Detection in 2 phases.

Approach

  1. Phase 1: slow = nums[0], fast = nums[0]. Move slow = nums[slow] and fast = nums[nums[fast]] until they meet.

  2. Phase 2: Reset slow = nums[0]. Advance both pointers 1 step at a time until they meet at cycle entry point.

  3. Return entry point value.

Naive Solution — Brute Force

Use a hash set to track seen numbers.

Python
class Solution:
    def findDuplicate(self, nums):
        seen = set()

        for num in nums:
            if num in seen:
                return num

            seen.add(num)

        return -1
C++
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        unordered_set<int> seen;
        for (auto num : nums) {
            if (seen.count(num)) {
                return num;
            }
            seen.insert(num);
        }
        return -1;
    }
};
Java
class Solution {
    public int findDuplicate(int[] nums) {
        Set<Integer> seen = new HashSet<>();
        for (int num : nums) {
            if (seen.contains(num)) {
                return num;
            }
            seen.add(num);
        }
        return -1;
    }
}
JavaScript
var findDuplicate = function(nums) {
    const seen = new Set();

    for (const num of nums) {
        if (seen.has(num)) {
            return num;
        }

        seen.add(num);
    }

    return -1;
};

Time: O(n) · Space: O(n)

Optimized Code (Python 3)

Python
class Solution:
    def findDuplicate(self, nums):
        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
C++
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int slow = nums[0];
        int 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;
    }
};
Java
class Solution {
    public int findDuplicate(int[] nums) {
        int slow = nums[0];
        int 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;
    }
}
JavaScript
var findDuplicate = function(nums) {
    let slow = nums[0];
    let 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;
};

Time: O(n) · Space: O(1)

Takeaway

Pattern — Array index mapping as Implicit Linked List Cycle Detection

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report