[LeetCode 287] 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.
Notice
- 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(n^2).
- There is only one duplicate number in the array, but it could be repeated more than once.
Example
Given nums
= [5,5,4,3,2,1]
return 5
Given nums
= [5,4,4,3,2,1]
return 4
Solution 1. O(n * log n) runtime, O(1) space, Binary Search on the max possible value n
1 public class Solution {
2 public int findDuplicate(int[] nums) {
3 if(nums == null || nums.length < 2){
4 return -1;
5 }
6 int start = 1, end = nums.length - 1;
7 while(start + 1 < end){
8 int mid = start + (end - start) / 2;
9 if(countSmallerAndEqual(mid, nums) <= mid){
10 start = mid;
11 }
12 else{
13 end = mid;
14 }
15 }
16 if(countSmallerAndEqual(start, nums) <= start){
17 return end;
18 }
19 return start;
20 }
21 private int countSmallerAndEqual(int mid, int[] nums){
22 int cnt = 0;
23 for(int i = 0; i < nums.length; i++){
24 if(nums[i] <= mid){
25 cnt++;
26 }
27 }
28 return cnt;
29 }
30 }
Solution 2. O(n) runtime, O(1) extra space, Linked List cycle detection, two pointers, slow and fast pointers
1 public class Solution {
2 public int findDuplicate(int[] nums) {
3 if(nums == null || nums.length < 2){
4 return -1;
5 }
6
7 int slow = nums[0];
8 int fast = nums[nums[0]];
9 while(slow != fast){
10 slow = nums[slow];
11 fast = nums[nums[fast]];
12 }
13 fast = 0;
14 while(slow != fast){
15 slow = nums[slow];
16 fast = nums[fast];
17 }
18 return slow;
19 }
20 }
Related Problems
Single Number
Linked List Cycle II