我的解法:
第一版:将数组中的元素看做新数组下标,每遇一个值,就对新数组的下标进行增值,最后再将新数组遍历一遍,查找出值>1的数,下标即为出现多次的数。
class Solution {
public int findRepeatNumber(int[] nums) {
int[] times = new int[nums.length];
for (int i : nums) {
times[i]++;
}
for (int i = 0; i < times.length; i++) {
if (times[i] > 1) {
return i;
}
}
return 0;
}
}
第二版:既然最后落脚点在判断出现次数,直接在增值计算时判断该值是否>1就可以了,省去遍历数组的步骤。
class Solution {
public int findRepeatNumber(int[] nums) {
int[] times = new int[nums.length];
for (int i : nums) {
times[i]++;
if (times[i] > 1) {
return i;
}
}
return 0;
}
}
其他解法:
利用set集合每个元素单次出现的特性:
public int findRepeatNumber(int[] nums) {
Set<Integer> times = new HashSet<>();
for (int i : nums) {
if (times.contains(i)) {
return i;
}
times.add(i);
}
return -1;
}
注:set和list都是插入并且list也有contain方法,但是在查找时,list采用遍历方式,而HashSet的查找是通过HashMap的KeySet来实现的,固调用方法时,set查找更快,当数字特别多,list速度会极慢。
原地置换:
public int findRepeatNumber4(int[] nums) {
int i = 0;
int[] a = {0, 1};
while(i<nums.length){
if(nums[i] == i){
i++;
continue;
}
if(nums[nums[i]] == nums[i]) {
return nums[i];
}
int temp = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = temp;
}
return -1;
}
该方法步骤:
通过遍历数组:
1.判断该数a与下标是否相同,
若相同:遍历数组下一个数
不相同:
再判断nums[a]与a是否相同
若相同则找到了重复出现的数
若不同将a与nums[a]交换
上述步骤总体是为了将数组中每一个元素放到以自身为下标的位置上,然后后续再由新数(b)作为下标判断该元素值(a),因为每个数都在自己的位置上,当b等于a,说明相同下标重复出现,即找到了该数。