Algorithm
Complexity
Data Structures
Optimization
Coding Techniques

Finding duplicates in On time and O1 space

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Finding duplicates in an array is a common problem in computer science and software engineering. A well-known challenge is to perform this operation in linear time, O(n)O(n), while also using constant space, O(1)O(1). This article delves into the methodologies, technical concepts, and strategies to achieve this efficiently.

Problem Statement

Given an array of integers, the goal is to identify any duplicates in O(n)O(n) time complexity while maintaining O(1)O(1) space complexity. The integers in the array should either be read-only or should not utilize any additional data structures for tracking duplicates.

Techniques for Finding Duplicates

Floyd’s Tortoise and Hare Cycle Detection

One of the most elegant solutions to this problem is leveraging Floyd's cycle detection algorithm, commonly known as the Tortoise and Hare algorithm. Although initially designed for linked lists to detect cycles, it can be adapted to find duplicates in an array.

How It Works

  1. Transform Array as a Linked List: Consider each element in the array as a node, and the value of the element as the next index pointer. The array thus simulates a linked list.
  2. Cycle Detection: If there is any duplicate number, then that means multiple indices point to the same next index, creating a cycle in our virtual linked list.
  3. Use Tortoise and Hare: Initialize two pointers, "tortoise" and "hare". Move tortoise at one step per iteration and hare at two steps. If there is a cycle, they will meet.
  4. Find Entry Point: Once the cycle is detected, initialize the hare to the start of the list. Move both pointers one step until they meet again at the cycle's start - the duplicate element.

Here is a Python implementation of the above logic:

python
1def find_duplicate(nums):
2    # Phase 1: Finding the intersection point within the cycle
3    tortoise = nums[0]
4    hare = nums[0]
5    
6    while True:
7        tortoise = nums[tortoise]
8        hare = nums[nums[hare]]
9        if tortoise == hare:
10            break
11    
12    # Phase 2: Finding the start of the cycle
13    hare = nums[0]
14    while hare != tortoise:
15        hare = nums[hare]
16        tortoise = nums[tortoise]
17    
18    return hare

Pros and Cons

  • Pros: Simple and efficient; does not modify the array; constant space and linear time.
  • Cons: Assumes the numbers are positive and within the list's index bounds. Doesn't identify multiple duplicates, only one during a single run.

A Summary of Key Techniques

TechniqueTime ComplexitySpace ComplexityCharacteristics
Floyd's Tortoise and HareO(n)O(n)O(1)O(1)Suitable for single duplicate in arrays; transforms array to list
Array Negation (Limited Range)O(n)O(n)O(1)O(1)Suitable for small range like 11 to nn; modifies input
Bit Manipulation MethodO(n2)O(n^2)O(1)O(1)Not suitable for larger inputs; often exceeds time constraints

Additional Considerations

Constraints and Assumptions

To apply these methods effectively, it's assumed:

  1. Constraints: The array consists of integers within a defined range. This is critical for the array negation technique.
  2. Read-only Arrays: For scenarios where modifications are not permitted, these approaches might need adjustments.

Handling Multiple Duplicates

When dealing with multiple duplicates, the above methods can be modified to run iteratively, identifying unique duplicates by resetting the cycle pointers. However, this typically increases complexity and is less efficient for a large number of duplicates.

Conclusion

Finding duplicates in linear time with constant space is achievable with clever applications of cycle detection algorithms. The adaptability of Floyd’s Tortoise and Hare, in particular, demonstrates the power of converting a challenging problem into a more manageable analog, like linked lists. Understanding these algorithms equips developers with tools to handle complex array operations efficiently.


Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.