algorithm
computer science
data structures
efficiency
programming

In less-than-linear time, find the duplicate in a sorted array

Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms

Introduction

Finding duplicates in an array is a common problem in computer science with numerous applications in data processing, error-checking systems, and more. In this article, we'll explore finding a duplicate in a sorted array in less-than-linear time. By leveraging the already sorted structure of the array, we can perform this operation efficiently. We'll examine the technical details, provide examples, and summarize key points.

Problem Statement

Given a sorted array, our objective is to identify any duplicate element in the array with time complexity better than O(n)O(n), where nn is the size of the array.

Prerequisites

  • Sorted Array: The array is sorted in non-decreasing order.
  • Duplicate Exists: At least one duplicate exists within the array.

Approaches to Finding a Duplicate

The key idea when dealing with sorted arrays is to leverage binary search, which operates in O(log⁡n)O(\log n) time complexity. Below is a binary search-based approach to find a duplicate:

  1. Concept: In a sorted array, duplicates will always be adjacent. Therefore, if we split the array at any midpoint, at least one half must contain an extra copy of a number.
  2. Algorithm:
    • Initialize two pointers: low to the start (0) and high to the end (n-1) of the array.
    • While low < high:
      • Find the mid-point: mid = low + (high - low) / 2.
      • Count numbers in the left half up to index mid.
      • If the count is greater than the number of unique numbers expected in the left half:
        • The duplicate must be in the left half. Set high = mid.
      • Otherwise:
        • The duplicate is in the right half. Set low = mid + 1.
    • The duplicate number is found when low == high.

Example Code (C++)

cpp
1#include <vector>
2#include <iostream>
3
4int findDuplicate(const std::vector<int>& nums) {
5    int low = 0;
6    int high = nums.size() - 1;
7
8    while (low < high) {
9        int mid = low + (high - low) / 2;
10        int count = 0;
11
12        // Count numbers less than or equal to `nums[mid]`
13        for (int num : nums) {
14            if (num <= nums[mid]) {
15                count++;
16            }
17        }
18
19        if (count > mid + 1) {
20            high = mid;
21        } else {
22            low = mid + 1;
23        }
24    }
25
26    return nums[low];
27}
28
29int main() {
30    std::vector<int> nums = {1, 2, 2, 3, 4};
31    std::cout << "Duplicate: " << findDuplicate(nums) << std::endl;
32    return 0;
33}

Time Complexity Analysis

Using binary search in this way has a time complexity of O(log⁡n⋅n)O(\log n \cdot n), where the nn factor arises from counting elements up to mid in each iteration. However, this approach is efficient given the logarithmic reduction in search space.

Key Insights

  1. Data Structure: Knowing that the array is sorted helps in significantly reducing the problem space. Binary search is naturally suited for sorted datasets.
  2. Adjacent Duplicates: In a sorted array, duplicates lie next to each other, simplifying the detection.

Summary Table

Key AspectDetails
Data RequirementSorted, contains duplicates
Optimal AlgorithmBinary Search
Time ComplexityO(log⁡n⋅n)O(\log n \cdot n)
Space ComplexityO(1)O(1) (original array not altered)
Example (Duplicate Element)[1, 2, 2, 3, 4] - Duplicate is 2

Conclusion

Finding duplicates in a sorted array can be done efficiently using binary search, taking advantage of the array’s sorted nature to achieve a time complexity of O(log⁡n⋅n)O(\log n \cdot n). This approach is optimal in scenarios where the array is large and performance is crucial. Implementing this method provides a robust solution to the problem of detecting duplicates in less-than-linear time.

In future studies, exploring alternative data structures or integration with parallel algorithms could further enhance performance, especially on large datasets.


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
Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms