---
# System prepended metadata

title: 0287. Find the Duplicate Number
tags: [Leetcode, Indexing Sort, Medium]

---

# 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;
    }
}
```