Find Dupes: An O(NLogN) Solution

Here is the problem (#423 in my solved list): https://leetcode.com/problems/find-the-duplicate-number/

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Example 1:
Input: [1,3,4,2,2]
Output: 2
Example 2:
Input: [3,1,3,4,2]
Output: 3
Note:
  1. You must not modify the array (assume the array is read only).
  2. You must use only constant, O(1) extra space.
  3. Your runtime complexity should be less than O(n2).
  4. There is only one duplicate number in the array, but it could be repeated more than once.

The key here are the two statements (conditions) in yellow above: no extra space, and some time complexity better than O(N^2). The first option that came to my mind then would be an O(NLogN): sort the array, and do a linear scan checking which two adjacent elements are the same, and when you find it, return. Code is below, cheers, ACC.

public class Solution
{
    public int FindDuplicate(int[] nums)
    {
        Array.Sort(nums);

        for (int i = 0; i < nums.Length - 1; i++)
        {
            if (nums[i] == nums[i + 1]) return nums[i];
        }
        return -1;
    }
}

Comments

  1. Great solution! It's possible to get a linear complexity though by looking at this problem from a different angle - imagine that each array element is a pointer to the next "node" forming a linked list. Now what does it mean to have 2 (or more) nodes in linked list that point to the same next node? Correct, a cycle. So we can use a famous Tortoise and Hare algorithm to find a cycle and its starting point (duplicate):

    class Solution {
    public:
    int findDuplicate(vector& nums) {
    int slow = nums.front();
    int fast = nums.front();
    while (true) {
    slow = nums[slow];
    fast = nums[nums[fast]];
    if (slow == fast) break;
    }
    slow = nums.front();
    while (slow != fast) {
    slow = nums[slow];
    fast = nums[fast];
    }
    return slow;
    }
    };

    ReplyDelete

Post a Comment

Popular posts from this blog

Advent of Code - Day 6, 2024: BFS and FSM

Golang vs. C#: performance characteristics (simple case study)

Advent of Code - Day 7, 2024: Backtracking and Eval