# 0287. Find the Duplicate Number
###### tags: `Leetcode` `Medium` `Indexing Sort`
Link: https://leetcode.com/problems/find-the-duplicate-number/
## 思路
类似[0442. Find All Duplicates in an Array](https://hackmd.io/UnpI8ph4Q6icK2K1UxDHfg)
**注意: 不能用异或是因为,input case里面可能有[2,2,2,2,2],不一定都是里面装了1,2,3,4的array**
### 思路一 $O(N)$ $O(N)$
set
### 思路二 $O(N)$ $O(1)$
**Negative Marking**
There are n+1 positive numbers in the array (nums) (all in the range [1,n]). Since the array only contains positive integers, we can track each number (num) that has been seen before by flipping the sign of the number located at index |num|, where || denotes absolute value.
For example, if the input array is [1,3,3,2], then for 1, flip the number at index 1, making the array [1,-3,3,2]. Next, for −3 flip the number at index 33, making the array [1,−3,3,−2]. Finally, when we reach the second 3, we'll notice that nums[3] is already negative, indicating that 3 has been seen before and hence is the duplicate number.
### 思路三 $O(N)$ $O(1)$
in-place变换
就是把每个数字num,放在nums[num-1],也就是让nums[num-1] = num, 如果nums[num-1]已经等于num了,还想往nums[num-1]里面放数字,就说明有重复了
### 思路四 $O(N)$ $O(1)$ without modifying original array
因为有重复的数字,所以用index找数字,一定会有circle
而能进到circle的entry就是duplicate number
假如nums[i] = a nums[j] = a 也就是nums[i]可以走到nums[a],一定有一条路径可以让nums[i]走到nums[j],然后就会又回到nums[a]
An explanation about finding the entry point part.
First assume when fast and slow meet, slow has moved $a$ steps, and fast has moved $2a$ steps. They meet in the circle, so the difference $a$ must be a multiple of the length of the circle.
Next assume the distance between beginning to the entry point is $x$, then we know that the slow has traveled in the circle for $a-x$ steps.
How do we find the entry point? Just let slow move for another $x$ steps, then slow will have moved $a$ steps in the circle, which is a multiple of length of the circle.
So we start another pointer at the beginning and let slow move with it. Remember $x$ is the distance between beginning to the entry point, after $x$ steps, both pointer will meet at the entry of circle.
## Code
### 思路二
```java=
class Solution {
public int findDuplicate(int[] nums) {
int duplicate = -1;
for(int i = 0;i < nums.length;i++){
int cur = Math.abs(nums[i]);
if(nums[cur]>0){
nums[cur]*=-1;
}
else{
duplicate = cur;
break;
}
}
for(int i = 0;i < nums.length;i++){
nums[i] = Math.abs(nums[i]);
}
return duplicate;
}
}
```
### 思路三
```java=
class Solution {
public int findDuplicate(int[] nums) {
int[] arr = nums;
for(int i = 0;i < arr.length;i++){
if(arr[i] == i+1) continue;
while(arr[i] != i+1){
int num = arr[i];
if(arr[num-1] == num) return num;
swap(arr, i, num-1);
}
}
return 0;
}
public void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
```
### 思路四
```java=
class Solution {
public int findDuplicate(int[] nums) {
int slow = nums[0];
int fast = nums[nums[0]];
while(slow!=fast){
slow = nums[slow];
fast = nums[nums[fast]];
}
fast = 0;
while(fast!=slow){
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
}
```