题目:
在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了多少次。请找出数组中任意一个重复的数字。
例:
如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或3.
思路:
本题可以用多种方法解决
1.遍历数组,预存上一个数字tmp,若tmp等于当前数字则返回当前数字,否则更改tmp的值即可。这种方法的时间复杂度为O(nlogn)
2.使用哈希表来解决,每扫描一个数字就判断一下是否在哈希表中。如果已存在,则输出该数字。这种方法时间复杂度为O(n),但空间复杂度因为使用哈希表的缘故也为O(n)。
3.为了保持时间复杂度为O(n),并且减少空间复杂度。还有另外一个方法,首先仍然重新扫描数字。当扫描到下标为i的数字时(该数字值为m),比较该数字是否等于i,若等于则不需要调整跳到下一个数字,若不相等,则与下标为m的数字比较,若相等,则找到重复数字,否则将两数字互换,此时下标m的数字与值对应,接下来再比较新的下标为i的数字。
public class Solution {
//使用Set接口的做法会创建一个集合,空间复杂度为O(n)
public void duplicate(String[] args) {
int[] array = new int[] {2,3,1,0,2,5,3};
Set<Integer> aset = new HashSet<>();
for (int i = 0; i <array.length ; i++) {
boolean isnew = aset.add(array[i]);
if (!isnew) System.out.println(array[i]);
}
}
}
public class Solution{
// 这种做法只交换数组内的值,因此空间复杂度为O(1)
public static void main(String[] args) {
int[] array = new int[] {2,3,1,0,2,5,3};
for (int i = 0; i <array.length ; i++) {
if (array[i]!=i) {
if(array[array[i]]==array[i]){
System.out.println(array[i]);
}
else
{
int tmp = array[i];
array[i] = array[array[i]];
array[tmp]=tmp;
}
}
}
}