题目描述
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
限制:
2 <= n <= 100000
代码
1 排序法 简单
class Solution_offer_3 {
public int findRepeatNumber(int[] nums) {
int result = 0;
Arrays.sort(nums);
for (int i = 1; i < nums.length; i++) {
if (nums[i-1] == nums[i]){
result = nums[i];
break;
}
}
return result;
}
}
2 用map的思路 用一个数组模拟map 牺牲空间
class Solution_offer_3 {
public int findRepeatNumber(int[] nums) {
int result = 0, len = nums.length;
int[] a = new int[len];
Arrays.fill(a,-1); //-1初始化数组
for (int i = 0; i < nums.length; i++) {
int index = nums[i];
if (a[index] != -1){ //说明a[index]之前已经变为1了 这里至少第二次访问了index 那么index这个值重复!
result = index;
break;
}
else{
a[index] = 1; //第一次访问index时,a[index]由-1变为1
}
}
return result;
}
}
3 不使用额外数组 用一个数组模拟map 给访问过的元素打标记
例如 [2,1,3,2]
下标 0 1 2 3
当我们访问nums[i]时 去找一下nums[nums[i]]的值 并把它取反(打标记),意为nums[i]已经出现过一次了,比如上面数组,i=0时 访问nums[0] = 2,
之后我们找nums[nums[0]] ,即nums[2] ,发现nums[2] = 3, 把它取反变为-3;
注意到当i = 3时,我们访问nums[3] = 2, 这时2第二次出现了,我们又会查看nums[2] ,这时发现它是-3 ,说明之前已经打过标记了 ,此时至少为第二次访问2这个值,所以2重复了!
class Solution_offer_3 {
public int findRepeatNumber(int[] nums) {
int result = 0;
for (int i = 0; i < nums.length; i++) {
int index = Math.abs(nums[i]); //为什么上绝对值 注意一下!!
if (nums[index] >= 0)
nums[index] = -nums[index];
else{
result = index;
break;
}
}
return result;
}
}