Day29 2023/03/30
难度:简单
题目
在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组(2,3,1,0,2,5,3),那么对应的输出是2或者3。存在不合法的输入的话输出-1。
数据范围:
进阶:时间复杂度 空间复杂度
示例
输入:(2,3,1,0,5,3)
输出:2
说明:2和3都是对的
思路
这道题可以使用哈希表来解决,时间复杂度为O(n),但需要额外的空间来存储哈希表。进阶要求时间复杂度为O(n),空间复杂度为O(1),可以使用数组本身作为哈希表,具体实现如下:
- 我们首先获取数组的长度
len,然后遍历数组中的每个数字。 - 如果当前数字不等于它的下标,那么就将它交换到正确的位置上,即交换到下标为它本身的位置上。
- 如果当前数字已经在正确的位置上,那么就说明这个数字重复了,返回它的值。如果遍历完成后没有找到重复数字,那么就返回-1。
关键点
- 因为题目要求所有数字都在0到n-1的范围内,其中n为数组长度,所以才使用数组作为哈希表,这样不会出现数组下标溢出的情况!!!
算法实现
c++代码实现-找到重复数字
#include <iostream>
#include <vector>
using namespace std;
// 找出数组中的重复元素
int FindDuplicateElem(vector<int> &nums) {
int len = nums.size(); // 数组长度
for (int i = 0; i < len; i++) {
// 如果当前数字没有再正确位置上,并且正确位置上已经存在正确元素了,说明该元素出现了重复
if (nums[i] != i && nums[nums[i]] == nums[i]) {
return nums[i]; // 返回重复元素
}
// 如果当前数字没有再正确位置上,但正确位置上并不存在正确元素了,说明该元素首次出现
if (nums[i] != i && nums[nums[i]] != nums[i]) {
swap(nums[i], nums[nums[i]]); // 将该元素放到它的正确位置下面
}
}
return -1; // 没有正确元素
}
int main() {
vector<int> nums = {2, 3, 1, 0, 2, 5, 3};
int res = FindDuplicateElem(nums);
cout << res << endl;
return 0;
}
- 时间复杂度 --- 遍历一次数组,其中n为数组长度。
- 空间复杂度 --- 在原数组上操作,且仅含常数级变量。
总结
本题,虽然是常用的哈希法,但如果大家善用题目中一些细小的条件,往往会产生一些意想不到的效果!!!😁