【LeetCode】面试题 03. 数组中重复的数字
一、遍历数组
由于只需要找出数组中任意一个重复的数字,因此遍历数组,遇到重复的数字即返回。为了判断一个数字是否重复遇到,使用集合存储已经遇到的数字,如果遇到的一个数字已经在集合中,则当前的数字是重复数字
class Solution {
public int findRepeatNumber(int[] nums) {
HashSet<Integer> hashSet = new HashSet<>();
for(int i = 0; i < nums.length; i++){
if(!hashSet.add(nums[i])){
return nums[i];
}
}
return -1;
}
}
- 时间复杂度:O(n),遍历数组一遍,使用哈希集合(HashSet),添加元素的时间复杂度为 O(1),故总的时间复杂度是 O(n)
- 空间复杂度:O(n),不重复的每个元素都可能存入集合,因此占用 O(n) 额外空间
二、原地置换
题干说,在一个长度为 n 的数组 nums 里的所有数字都在 0~n -1 的范围内。此说明含义:数组元素的索引和值是一对多的关系。因此,可以遍历数组并通过交换的操作,使元素的索引与值一一对应。因而,就能通过索引映射对应的值,起到与字典等价的作用。遍历中,第一次遇到数字 x 时,将其交换至索引 x 处,而第二次遇到数字 x 时,一定有 nums[x] = x,此时即可得到一组重复的数字
class Solution {
public int findRepeatNumber(int[] nums) {
int i = 0;
while(i < nums.length){
if(nums[i] == i){ //如果当前数和下标对应则 i++ 换一个数
i++;
continue;
}
//如果当前数对应的下标已经有相同数了,则说明当前数就是一个重复数
if(nums[nums[i]] == nums[i]) return nums[i];
//如果当前数和下标不对应,则可以用它来作为辅助变量,将数置换到对应的下标去
int t = nums[i]; //保存当前数
nums[i] = nums[t]; //将对应下标原本的数置换到这里
nums[t] = t; //将当前数置换到对应下标
}
return -1;
}
}
- 时间复杂度 O(N):遍历数组使用 O(N),每轮遍历的判断和交换操作使用 O(1)
- 空间复杂度 O(1):使用常数复杂度的额外空间