1. 题目描述
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
2. 题目分析
- 此题考查的是面试者的沟通能力,在面试官给出此题时,要询问面试官允许的时间复杂度和空间复杂度
- 关于此题,有三种解法,对应着三种不同的时间空间复杂度:
排序: 时间: O(nlogn) 空间O(1) HashMap: 时间: O(n) 空间O(n) 根据题目信息,按数值和下标:时间:O(n) 空间: O(1)
- 排序的解法:进行快排,然后
nums[i] != i
,返回nums[i]; - HashMap的解法:初次出现时
map.put(nums[i], 1);
再一次出现时,直接返回nums[i] - 数值和下标的解法:从下标0开始,将num[i]放在下标为num[i]的位置,如果坐标num[i]的值已经是num[i],则返回num[i];
例如:1 0 2 3 5 2 当前指针为0 1 != 0 所以将1和0交换 0 1 2 3 4 5 2 0 == 0 指针++ 1 == 1 指针++ 2 == 2 指针++ 3 == 3 指针++ 4 == 4 指针++ 5 == 5 指针++ 2 != 6,但是目前下标2已经有2了,所以2是重复的
3. 题目代码
3.1 HashMap解法
public int findRepeatNumber(int[] nums) { HashMap<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { if (map.containsKey(nums[i])) { return nums[i]; } else { map.put(nums[i], 1); } } return 0; }
3.2 数值与下标
public static int findRepeatNumber1(int[] nums) { int i = 0; while (i < nums.length) { if (nums[i] == i) { i++; continue; // } if (nums[i] == nums[nums[i]]) { return nums[i]; } // 这里需要注意,在进行交换时,一定要写nums[i] = nums[temp]; // 不能写成nums[nums[i]] = nums[i]; 因为在第二步时,我们的nums[i]已经被改变 int temp = nums[i]; nums[i] = nums[temp]; nums[temp] = temp; } // -1:未被查到有重复的 return -1; }