# Sword finger offer 03: duplicate number of array species

## problem

Find duplicate numbers in the array.

All numbers in an array num of length n are in the range of 0 ~ n-1. Some numbers in the array are repeated, but I don't know how many numbers are repeated, or how many times each number is repeated. Please find any duplicate number in the array.

### Example 1

Input: [2, 3, 1, 0, 2, 5, 3]

Output: 2 or 3

## Solution I

### Idea: sorting + traversal

- First, sort the data,
- After sorting, traverse the data. If you encounter the same data, return immediately.
- Time complexity O(nlogn), space complexity O(logn)

### Specific implementation: java

class Solution { public int findRepeatNumber(int[] nums) { Arrays.sort(nums); int compare = nums[0]; for (int i = 1; i < nums.length; i++) { if (compare == nums[i]) { return compare; } else { compare = nums[i]; } } return -1; } }

## Solution II

### Idea: hash table

- Traverse the array, taking the data as the key of the hash table and the number as the value
- If a key is found to exist, the data will be returned directly
- Time complexity O(n), space complexity O(n)

### Specific implementation: java

class Solution { public int findRepeatNumber(int[] nums) { HashMap<Integer,Integer> map = new HashMap<>(nums.length); for(int i = 0;i<nums.length;i++){ if(map.get(nums[i])==null){ map.put(nums[i],1); } else{ return nums[i]; } } return -1; } }

## Solution III

### Idea: Conflict of laws

#### analysis:

We can know that all numbers are in the range of 0~n-1, so we can know: if there is no conflict at all, there must be one number for each number of 0-n-1, then we can take the following table of the array as the key, and there must be duplicate keys. Just find the duplicate key

- Traverse the array and put the data in the corresponding subscript. If the subscripts conflict, the data will be returned. If there is no conflict, the data will be exchanged with the current data location
- For example: [2, 3, 1, 0, 2, 5, 3]
- First time: [1,3,2,0,2,5,3]
- Second time: [3,1,2,0,2,5,3]
- Third time: [0,1,2,3,2,5,3]
- The fourth time, 2 conflicts, return directly to 2
- Time complexity O(n), space complexity O(1)

class Solution { public int findRepeatNumber(int[] nums) { for (int i = 0; i < nums.length; ) { if (i==nums[i]){ i++; continue; } if (nums[nums[i]] == nums[i]) { return nums[i]; } else { int t = nums[i]; nums[i] = nums[t]; nums[t] = t; } } return -1; } }

## Problem change 1

If you need to find all the same numbers, is the above method still effective?

- All can be realized (it is recommended to try by yourself)

## Problem change 2

All numbers in an array with length n+1 are in the range of 1~n, so at least one number in the array is repeated. Please find any duplicate number in the array, but you cannot modify the input array.

## Solution I

### Idea: copy array

- First, copy the array.
- Then use any solution of the original problem

Code reference above

### Solution II

### Idea: the idea of binary search

#### analysis:

We divide the number of 1n into two parts from the middle number m, generally 1m in the front and m+1n in the back. If the number of 1m numbers exceeds m, the interval of this version must contain duplicate numbers; If the two intervals are equal, move the position of M forward one bit and compare it. Take this as the idea

- For example, array [1,2,2,4,5]
- The first comparison: m is 3; 1-3 and 4-5 have 3 and 2 respectively. Indistinguishable, moving m=2
- The second comparison: m is 2; 1-2 and 3-5 have 3 and 2 respectively. There must be duplicate numbers in interval 1-2
- The third comparison: m is 1; 1 is 1 time, 2 is 2 times. Duplicate number is 2
- Time complexity O(nlogn), space complexity O(1)

public int findRepeatNumber(int[] nums){ if (null == nums || nums.length == 0 || nums.length == 1) { return -1; } int left = 1; int right = nums.length; int mid = left + (right - left) / 2; while (left <= right) { int preNums = mid - left + 1; int pre = countRange(nums ,left, mid); if (pre == preNums) { mid = mid - 1; //Boundary value if (mid < left){ mid = left + (right - left) / 2; left = mid + 1; mid = left + (right - left) / 2; } } else if (pre < preNums) { if (left == right) { return left; } left = mid + 1; mid = left + (right - left) / 2; } else { if (left == right) { return left; } right = mid; mid = left + (right - left) / 2; } } return -1; }

reference resources: Binary search