0%

剑指offer001 寻找重复数组元素

Problem:

在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
要求时间复杂度 O(N),空间复杂度 O(1)

Input:
{2, 3, 1, 0, 2, 5}

Output:
2

Intuition:

对于这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素调整到第 i 个位置上进行求解。
以 (2, 3, 1, 0, 2, 5) 为例,遍历到位置 4 时,该位置上的数为 2,但是第 2 个位置上已经有一个 2 的值了,因此可以知道 2 重复:

Solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class CodingInterview_001 {
public static void main(String[] args) {
int[] a=new int[]{2,3,4,0,3,5};
int ans=findRepeatNum(a);
if(ans==-1){
System.out.println("There isn't any repeat number.");
}else{
System.out.println(ans);
}
}

public static int findRepeatNum(int[] duplicate){
if(duplicate==null||duplicate.length<0){
return -1;
}
//我们在循环中保证看到一个元素i,就把它放到数组的第i个格子里。那么如果数组中有重复元素就等价于我
//在对某个元素j换位置的时候发现元素j所在的格子装的数也是j(因为题目已经限定好了数字是从0-n-1)
for(int i=0;i<duplicate.length;i++){
//如果duplicate[i]里装的就是i那么我们就什么都不做,直接把下标往后移
if(duplicate[i]!=i&&duplicate[duplicate[i]]==duplicate[i]){
return duplicate[i];
}else if(duplicate[i]!=i){
swap(duplicate,i,duplicate[i]);
}

}
return -1;
}

private static void swap(int[] duplicate,int index1,int index2){
int temp=duplicate[index1];
duplicate[index1]=duplicate[index2];
duplicate[index2]=temp;
}

}