在一个长度为n
的数组nums
里的所有数字都在0~n-1的范围内。数组中的某些数字是重复的,但不知道有几个数字重复了,也不知道每个数组重复了几次。请找出数组中任意一个重复的数字。
示例1:
输入:[]2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
限制:2 <= n <= 100000
解答
本题虽然是简单题,但如果要在面试的时候遇到,可以多问面试官一句,他的需求是什么,如果是时间优先,那么可以使用字典来做;如果是空间优先,那么可以原地排序数组,然后遍历;如果要求时间复杂度O(n),空间复杂度O(1)。可以用一种原地哈希的方法,但这个方法有局限性,不是普适性方法。
// 1. 字典
int findRepeatNumber(vector<int>& nums) {
// 因为set中是不能存在重复值的,所以当set的长度与已经插入的元素个数不等时,说明存在重复元素
unordered_set<int> numbers;
int n = nums.size();
for (int i = 0; i < n; ++i)
{
numbers.insert(nums[i]);
int l = numbers.size();
if (l != i + 1)
return nums[i];
}
return -1;
}
// 2. 原地排序
int findRepeatNumber(vector<int>& nums) {
// 原地排序之后,有重复的元素必定相邻,因此遍历数组,判断相邻元素是否相等即可
int n = nums.size();
sort(nums.begin(), nums.end());
for (int i = 0; i < n - 1; ++i)
{
if (nums[i] == nums[i + 1])
return nums[i];
}
return -1;
}
// 3. 原地哈希
int findRepeatNumber(vector<int>& nums) {
// 这个方法属于一种特解,它的关键在于题中所说的有n个在0~n-1范围内的数
// 当一个元素的值为n时,就把元素n移到数组中下标为n的位置,这样当出现重复元素n的时候,下标为n的位置已经有n了,就说明有重复元素
int n = nums.size();
for (int i = 0; i < n; ++i)
{
while (i != nums[i])
{
if (nums[i] == nums[nums[i]])
return nums[i];
swap(nums[i], nums[nums[i]]);
}
}
return -1;
)
本文题目及部分解答来自力扣:03.数组中重复的数字