Given an array nums containing n + 1 integers where each integer is between 1 andn (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Note:
O(n2)
.
The most straight forward way is to use hashmap..... However, the note said O(1) space allowed. hmm, after reading the note, there is a clue...
There are a few algorithm complexity less then O(n2). Sort -> nlgn. In this case, we need to sort the inputs first and then use binary search to find the element.
Suppose, we have a sorted array. How to apply binary search is the main trick here.
So, let's make several examples
[1, 2, 2, 2, 3]:
First Round: left = 0, right = 4, mid = 2, nums[mid] = 2 < mid + 1.... .We thus know that the duplicate number is on the left. Thus, right = mid;
Second Round: left = 0, right = 2, mid = 1, nums[mid] = 2 == mid + 1, we thus know that the duplicate number is on the right. Thus, left = mid;
Third Round: left = 1, right 2, ---> in this case, only two elements left, the duplicate is in them two.We dont need to apply binary search anymore. Since, left(1) have been verified in Secound Round. Thus, Duplicate = nums[right].
[1, 2, 3, 4, 4]
First Round: left = 0, right = 4, mid = 2, nums[mid] = 3 == mid + 1, we thus know that the duplicate number is on the right. Thus, left = mid;
Second Round: left = 2, right = 4, mid = 3, nums[mid] = 4 == mid + 1, we thus know that the duplicate number is on the right. Thus, left = mid;
Third Round: left = 3, right = 4 --> in this case, there are only two elements left, the duplicate is in them two.Since we know that 3 is not the duplicate from the second round. Then, nums[right] must be the duplicate.
[1, 2, 4, 5, 7, 7, 7, 7, 8]
First Round: left = 0, right = 8, mid = 4, nums[mid] = 7 > mid + 1, we thus know that the duplicate number must be on the right. thus, left = mid;
Second Round: left = 4, right = 8, mid = 6, nums[mid] = 7 == mid + 1, we thus know that the duplicate must be on the right. Thus, left = mid;
Third Round: left = 6, right = 8, mid = 7, nums[mid] = 7 < mid + 1, we thus know that the duplicate must be on the left. Thus, right = mid;
Fourth Round: left = 6, right = 7. ---> in this case, there are only two elements left.The duplicate must be in them two. Since we know that nums[6] is not the duplicate from the second round,then, nums[right] is the duplicate.
#include <vector> #include <iostream> #include <algorithm> using namespace std; int findDuplicate(vector<int>& nums) { if(nums.size() <= 1) return -1; sort(nums.begin(), nums.end()); // nlgn time complexity. // binary search then. int left = 0, right = nums.size() - 1; while(left < right - 1) { int mid = left + (right - left) / 2; if(nums[mid] >= mid + 1) left = mid; else right = mid; } return nums[right]; } int main(void) { vector<int> nums{7, 9, 7, 4, 2, 8, 7, 7, 1, 5}; int target = findDuplicate(nums); cout << target << endl; }