目录
题目
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。
数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。
请找出数组中任意一个重复的数字。
示例 1:
输入:[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
解法一:使用HashSet集合记录出现的次数
- 使用集合存储已遍历的数据,新数据遍历时,判断是否在集合中存在重复的数据
//第一种解法
public static int findRepeatNumber(int[] nums){
//1.创建Set集合,将测试的数组存入集合中
Set<Integer> set = new HashSet<>();
for (int number : nums){
//2.遍历传递进来的数组,将数组中的元素存入HashSet集合中
//遍历数组快捷键 iter快捷键是一个增强for循环,查找每一个遍历出来的值
if (set.contains(number)){
System.out.println("发现重复元素"+number);
return number;
//3.使用HashSet集合中的Contains方法,
//判断若第二次存入与之前有相同的元素就将这个元素返回
}
System.out.println("添加元素:"+number);
set.add(number);
}
//若循环一遍数组中没有出现重复的数据,则返回-1
return -1;//作为占位符,因为这个元素只会在0到n-1的范围内,-1就代表没有
}
解法二:先排序后查找
- 将数组排序后重复元素相邻
//解法二
public static int findRepeatNumberOne(int[] nums){
//Arrays类是java提供的操作数组的工具
System.out.println(Arrays.toString(nums));
Arrays.sort(nums);//sort方法是用来排序(从小到大排序)的
System.out.println(Arrays.toString(nums));
//itar快捷键普通的for循环
//通过判断相邻元素是否相等,返回是否重复
for (int i = 1; i < nums.length; i++) {
if(nums[i]==nums[i-1]){
return nums[i];
}
}
return -1;
}
解法三:使用临时数组
因为长度为 n 的数组 nums 里的所有数字都在 0~n-1的范围内,.
所以临时数组中的索引对应所有可能出现的数字 ,遍历时将出现数字对应到临时数组的索引位置更改元素值 0 改为 1
当临时数组的元素不为0时说明此索引位置已经出现过元素了
[2, 3, 1, 0, 2, 5, 3]
[0, 0, 0, 0, 0, 0, 0]
0 1 2 3 4 5 6
[0, 0, 1, 0, 0, 0, 0]
[0, 0, 1, 1, 0, 0, 0]
[0, 1, 1, 1, 0, 0, 0]
[1, 1, 1, 1, 0, 0, 0]
代码:注意:一定是先判断临时数组中的num索引位置的元素是否等于0,然后再赋值
public static int findRepeatNumberTwo(int[] nums){
//{5, 3, 1, 0, 2, 5, 3}
//先判断临时数组中的num索引位置的元素是否等于0,然后再赋值
//定义一个临时数组,临时数组中的所有元素默认都是0
int[] temp = new int[nums.length];
System.out.println(Arrays.toString(nums));
for (int i = 0; i < nums.length; i++) {
int num = nums[i];
//如果已经赋值代表nums中的元素重复出现
if (temp[num] != 0 ){
//若临时数组中对应的num索引的值temp[num]不等于0就证明当前的num值是重复的
return num;
}
//找到临时数组的索引位置赋值为1
temp[num]=1;
System.out.println(Arrays.toString(temp));
}
return -1;
}
解法四:交换位置查找
分析:
[2, 3, 1, 0, 2, 5, 3]
0 1 2 3 4 5 6
[0, 1, 2, 3, 2, 5, 3]
0 1 2 3 4 5 6
[2, 3, 1, 0, 2, 5, 3]
解题思路:
遍历数组的过程中,希望当前位置 和 出现元素正好匹配上。
先判断 ,是否匹配 , 如果不匹配 则进行交换 并且看当前索引位置的值是否与元素的值相同。
如果可以交换 ,交换之后 ,继续遍历当前位置 如果不可交换 即为重复元素 。
0 1 2 3 4 5 6
遍历2 交换2和1 [1,3,2,0,2, 5,3]
遍历1 交换1和3 [3,1,2,,0,2,5,3]
遍历3 交换3和0 [0,1,2,3,2,5,3]
遍历0 不交换
遍历1 不交换
遍历2 不交换
遍历3 不交换
遍历2 已经出现期望元素 是重复元素
public static int findRepeatNumberTwo(int[] nums){
System.out.println(Arrays.toString(nums));
// [2, 3, 1, 0, 2, 5, 3]
for (int i = 0; i < nums.length; i++) {
// 如果索引正好等于元素本身 是期望的结果 则跳过此次循环,进入下一循环
if (nums[i] == i) continue;
// i = 0
int num = nums[i]; // 2
if (nums[num] == num) {
// 如果当前索引位置的元素和当前索引是相等的话,说明有重复的数据,返回当前元素
System.out.println("当前索引为" + num + "的位置 已经有" + num + "值,重复了");
return num;
}
//交换位置,
int tmp = nums[num]; // 1
nums[num] = num;
nums[i] = tmp;
// [1, 3, 2, 0, 2, 5, 3]
// 交换仍需遍历当前位置的值 所以抵消i++
i--;
System.out.println(Arrays.toString(nums));
}
return -1;
}