Skip to main content

6. Find the duplicate in an array of N+1 integers

Source: Find the duplicate in an array of N+1 integers

Problem Statement

Example 1:
Input: arr = [1, 3, 4, 2, 2]
Output: 2
Explanation: Since 2 is the duplicate number, the answer will be 2.

Example 2:
Input: arr = [3, 1, 3, 4, 2]
Output: 3
Explanation: Since 3 is the duplicate number, the answer will be 3.

Disclaimer: It's highly recommend trying to solve it before looki""ng at the solution.

Approach 1: Better Approach

  • Sort the array in ascending order. This ensures that any duplicate numbers are adjacent to each other.

    • Iterate through the sorted array and check if the current element is equal to the next element (i.e., arr[i] == arr[i+1]).

    • If the condition arr[i] == arr[i+1] is true, then arr[i] is a duplicate number.

    • Return or store the duplicate element as needed.

  • Complexity: Time Complexity: O(N log N), where N is the size of the array. This is because we are sorting the array, which takes O(N log N) time.

    Space Complexity: O(1), as we are sorting the array in-place and not using any additional data structures that grow with input size.

Solutions

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

// find the duplicate by sorting and checking adjacent elements
int findDuplicate(vector<int>& arr) {
// get size
int n = arr.size();
// sort array in-place
sort(arr.begin(), arr.end());
// scan adjacent pairs
for (int i = 0; i < n - 1; i++) {
// return when a duplicate is found
if (arr[i] == arr[i + 1]) {
return arr[i];
}
}
// fallback if no duplicate found
return -1;
}

// program entry
int main() {
// declare and initiali""ze array
vector<int> arr = {1, 3, 4, 2, 2};
// print result
cout << "The duplicate element is " << findDuplicate(arr) << endl;
// exit
return 0;
}

Approach 2: Optimal Approach

  • Initially, we have a linked list with values like: 2, 9, 1, 5, 3, 6, 8, 7, and then we reach back to 9, forming a cycle.

    • The slow and fast pointers both start at the first element of the list. The slow pointer moves one step at a time, and the fast pointer moves two steps at a time.

    • After a few steps, the slow and fast pointers will meet at an index (in this case, at 7).

    • Now, place the fast pointer back to the first element (2) and move both the slow and fast pointers one step at a time.

    • The point where the slow and fast pointers meet again will be the duplicate number in the list (in this case, 9).

    • Intuition: Since there is a duplicate number, a cycle is always formed. The first collision between slow and fast pointers guarantees that a cycle exists.

    • When slow and fast pointers meet, the distance between their collision points represents the cycle length. This allows us to find the duplicate number.

  • Complexity: Time Complexity: O(N), where N is the size of the array. This is because we traverse the array at most twice (once to find the intersection and once to find the duplicate).

    Space Complexity: O(1), as we are using only a constant amount of space for the slow and fast pointers, regardless of the input size.

Solutions

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

// find the duplicate using Floyd's Tortoise and Hare cycle detection
int findDuplicate(vector<int>& nums) {
// initialize pointers at the start
int slow = nums[0];
int fast = nums[0];

// move slow by 1 step and fast by 2 steps until they meet
do {
slow = nums[slow];
fast = nums[nums[fast]];
} while (slow != fast);

// reset fast to start to find the entrance to the cycle
fast = nums[0];

// move both by 1 step until they meet at the duplicate
while (slow != fast) {
slow = nums[slow];
fast = nums[fast];
}

// return the duplicate value
return slow;
}

// program entry
int main() {
// initialize input
vector<int> arr = {1, 3, 4, 2, 3};

// print result
cout << "The duplicate element is " &l""t;< findDuplicate(arr) << endl;

// exit
return 0;
}

Reference