Find Dupes: An O(NLogN) Solution
Here is the problem (#423 in my solved list): https://leetcode.com/problems/find-the-duplicate-number/
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.
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:
- You must not modify the array (assume the array is read only).
- You must use only constant, O(1) extra space.
- Your runtime complexity should be less than O(n2).
- 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; } }
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):
ReplyDeleteclass 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;
}
};