题目一:找出数组中重复的数字
在一个长度为n的数组里的所有数字都在0~n-1范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。
题解1:
思路:先将数字排序,然后遍历数组,找出重复的数字。(排序时间:O(nlogn))
代码实现:
/*
排序+遍历的方式找出数组中重复的数字
*/
public static void duplicateNum(int []arr)
{
Arrays.sort(arr);
for (int i=1;i<arr.length;i++)
if (arr[i]==arr[i-1])
System.out.println(arr[i]);
}
题解2:
思路:构建一个哈希表,遍历数组所有数字,判断哈希表中是否存在这个数字,如果没有,则添加进哈希表。如果已经存在,则输出该值。
代码实现:
public static void duplicateNum(int []arr)
{
HashMap hashMap = new HashMap(); //新建一个hashmap
for (int i=0;i<arr.length;i++) //遍历数组中的元素
{
//如果hash表中没有该数字,添加并以其本身作为关联键
if (!hashMap.containsKey(arr[i]))
hashMap.put(arr[i],arr[i]);
else
//如果存在该数字了,说明出现重复数字,则打印该数字
System.out.println(arr[i]);
}
System.out.println(hashMap);
}
题解3:
思路:由于题目中的数组中数字都在0~n-1范围内,所以在我们排序数组之后,如果这个数组中无重复数字(假设为{0,1,2,3,4,5,6}),那么数字arr[i]将会与其下标相同;一一对应成以下情况:
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
如果有重复数字(以题目中所给数组为例{0,1,2,2,3,3,5}),同样将其一一对应成以下情况:
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
值 | 0 | 1 | 2 | 3 | null | 5 | null |
2 | 3 |
出现了一些位置存在多个值,一些位置为空(null)。
而实际上排序的元素在数组中的对应情况应该是:
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
值 | 0 | 1 | 2 | 2 | 3 | 3 | 5 |
所以可以对原数组({2,3,1,0,2,5,3})进行检索,步骤如下:
① 从数组第0位开始检索,arr[0]=2,所以arr[0]!=0,则将其与下标为2的那个数交换位置,即arr[0](值为2)与arr[2](值为1)交换,得到新数组:{1,3,2,0,2,5,3}
② 新数组{1,3,2,0,2,5,3}第0位arr[0]=1,仍然有arr[0]!=0,则重复上一次操作,即arr[0](值为1)与arr[1](值为3)交换,得到新数组:{3,1,2,0,2,5,3}
③ 继续重复上一次操作,将arr[0](值为3)与arr[3](值为0)交换,得到新数组:{0,1,2,3,2,5,3}
④ 此时数组第0,1,2,3位置上的值arr[i]都与之下标i相同,直到下标为4时,值与下标不同了,arr[4]=2,当我们继续将其作交换操作时,我们发现arr[4](值为2)与arr[2](值为2)两者的值是相同的,此时我们就找到了第一个相同数字2,就可以输出其值,然后跳出此次循环,继续检索下一个位置。
⑤ 重复检索直到最后一个位置的数字完成时,程序结束。
代码实现:
public static void duplicateNum(int []arr)
{
//判断数组是否为空
if (arr==null||arr.length<1)
return;
//判断数组中数字是否满足0~n-1范围内的先决条件
for (int i=0;i<arr.length;i++)
if ( arr[i] < 0 || arr[i] > arr.length - 1)
return;
int temp=0;
for (int i=0;i<arr.length;i++)
while (arr[i]!=i)
{
if (arr[i]==arr[arr[i]])
{
System.out.println(arr[i]);
break;
}
else
{
temp = arr[i];
arr[i] = arr[temp];
arr[temp] = temp;
}
}
}
PS:该解法只能在满足先决条件(所有数字满足在[0,n-1]范围内)时才实用,所以需要提前判断是否满足条件。