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.
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.
Solution:
Method 1: Floyd Loop Detection
This is a classic interview question. Donald Knuth took 24 hours to come up with an O(n) time and O(1) space solution.
If the input is [4, 2, 3, 5, 1, 3], and the duplicate number is 3.
We iterate the array by using the value as index. So the output of the above array is:
nums[0] = 4
nums[4] = 1
nums[1] = 2
nums[2] = 3
nums[3] = 5
nums[5] = 3
nums[3] = 5
nums[5] = 3
...
We write these numbers down.
4 --> 1 --> 2 --> 3 --> 5
^ |
| v
------
We found a cycle!
Now the problem becomes the Floyd loop detection problem and we use two pointers to find the entry of the loop.
Code:
public class Solution { public int findDuplicate(int[] nums) { int fast = 0; int slow = 0; do { fast = nums[nums[fast]]; slow = nums[slow]; } while(slow != fast); int find = 0; while (find != slow) { slow = nums[slow]; find = nums[find]; } return find; } }
Method 2: Brute Force, O(n2) time and O(1) space
Method 3: HashSet, O(n) time and O(n) space
Method 4: Binary Search O(nlogn) time and O(1) space