题目:
03.找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。(2<=n<=100000)
示例 1:
输入: [2, 3, 1, 0, 2, 5, 3] 输出:2 或 3
思路:
这题我用了三种思路:
-
使用哈希表。要查找数组中的重复值,可以使用哈希表记录该数组中的值,当查找到重复值时直接返回即可。
-
原地交换。题目中给出关键信息,在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。也就是说数组下标和数组元素是一对多的关系。
可以将下标与值一一对应,直到遇到重复值。
-
排序比较。使用Array工具类中的sort()方法使数组排序,接着nums[i]和nums[i+1]进行比较,若相等则直接返回nums[i]。
具体流程:
方法一:哈希表
1.创建哈希表dic
2.依次判断数组中的元素是否在哈希表中有相同元素。
3.若有则直接返回;若没有则将该元素记录到哈希表中。
4.重复2,3步直到数组遍历完全,若遍历完尚未返回,返回-1。
class Solution {
public int findRepeatNumber(int[] nums) {
Set<Integer> dic=new HashSet<>();
for(int i=0;i<nums.length;i++){//这里for循环可改为for(int num:nums)num等同于nums[i]
if(dic.contains(nums[i])) return nums[i];
dic.add(nums[i]);
}
return -1;
}
}
执行结果:
方法二:原地交换
1.循环判断索引i与对应元素nums[i]是否相等,
2.相等则i+1;不相等则判断nums[i]与nums[nums[i]]是否相等,
若相等则直接返回nums[i];若不相等则将两值替换位置。
3.循环第二步判断,直到索引i与对应元素nums[i]相等。
4.若遍历完尚未返回,则返回-1。
注意:方法二的解法有一个关键点是只有 nums[i] == i 的时候i才递增,这样保证找到相同元素前不会漏掉某些元素的处理。否则很容易变成以下做法。
错误做法:
class Solution {
public static int findRepeatNumber(int[] nums) { //原地交换
int x=0;
for(int i=0;i<nums.length;i++){
if(nums[i]==i)
continue;
else if(nums[nums[i]]!=nums[i]) {
x = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = x;
}
else return nums[i];
}
return -1;
}
}
正确做法:
class Solution {
public static int findRepeatNumber(int[] nums) { //原地交换
int x=0;
for(int i=0;i<nums.length;i++){
while(nums[i]!=i) //关键点,没有这步可能会遗漏元素。
{
if (nums[nums[i]] != nums[i]) {
x = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = x;
} else return nums[i];
}
}
return -1;
}
}
执行结果:
方法三:排序比较
1.使用Array类中的sort()方法对数组进行排序。
2.将数组中的元素nums[i]和nums[i+1]进行比较。
若相同则直接返回nums[i]。
3.若遍历完尚未返回,则返回-1。
class Solution {
public static int findRepeatNumber(int[] nums) { //排序两两比较法
Arrays.sort(nums);
for (int i = 0; i <nums.length-1 ; i++) {
if( nums[i]==nums[i+1])
return nums[i];
}
return -1;
}
}
执行结果: