找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
方法一:
将数组进行排序,需要O(nlogn)的时间,然后再用两个指针扫描一遍数组即可。
这里排序的时候,刚开始直接用的sort函数,之后尝试自己写了一个简单的快排逻辑。
int Partition(vector<int>& vec, int low, int high)
{
srand(time(0));
int num = low + rand() % (high - low);
swap(vec[low], vec[num]);
int pivot = vec[low];
while (low < high)
{
while (low < high && vec[high] >= pivot) high--;
swap(vec[low], vec[high]);
while (low < high && vec[low] <= pivot) low++;
swap(vec[low], vec[high]);
}
vec[low] = pivot;
return low;
}
void QuickSort(vector<int>& vec, int low, int high)
{
if (low < high)
{
int postion = Partition(vec, low, high);
QuickSort(vec, low, postion - 1);
QuickSort(vec, postion + 1, high);
}
}
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
QuickSort(nums, 0, nums.size() - 1);
//sort(nums.begin(), nums.end());
for(int i = 0, j = 1; i < nums.size() && j < nums.size(); i++, j++)
{
if(nums[i] == nums[j])
{
return nums[i];
}
}
return 0;
}
};
方法二:
采用哈希表来解决,从头到尾按顺序扫描数组的每个数字,每扫描到一个数字的时候,都可以用O(1)的时间复杂度来判断哈希表里面是否已经包含该数字。如果哈希表里已存在该数字,就找到一个重复的数字。这个算法的时间复杂度是O(n),空间复杂度为O(n)。
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
unordered_set<int> hash_table;
for (int i = 0; i < nums.size(); i++)
{
if (hash_table.find(nums[i]) == hash_table.end())
{
hash_table.insert(nums[i]);
}
else
{
return nums[i];
}
}
return 0;
}
};
方法三:
数组中的数字都是在0~n-1的范围内。如果这个数组中没有重复的数字,那么当数组排序之后数字i将出现在下标为i的位置。由于数组中有重复的数字,有些位置可能存在多个数字,同时有些位置可能没有数字。
当扫描到下标为i的数字时,首先比较这个数字(用m表示)是不是i。如果是,则接着扫描下一个数字;如果不是,则再拿它和第m个数字进行比较。如果它和第m个数字相等,就找到了一个重复的数字(该数字在下标i和m的位置都出现了)。如果它和第m个数字不相等,就把第i个数字和第m个数字交换,把m放到属于它的位置。接下来再重复这个比较交换的过程,直至我们发现一个重复的数字。
class Solution {
public:
int findRepeatNumber(vector<int>& arr) {
for (int i = 0; i < arr.size(); i++)
{
while (arr[i] != i)
{
if (arr[i] == arr[arr[i]])
return arr[i];
else
swap(arr[i], arr[arr[i]]);
}
}
return 0;
}
};
最后附上官方代码:
bool duplicate(int numbers[], int length, int* duplication)
{
if (numbers == nullptr || length <= 0)
{
return false;
}
for (int i = 0; i < length; ++i)
{
if (numbers[i] < 0 || numbers[i] > length - 1)
return false;
}
for (int i = 0; i < length; i++)
{
while (numbers[i] != i)
{
if (numbers[i] == numbers[numbers[i]])
{
*duplication = numbers[i];
return false;
}
int temp = numbers[i];
numbers[i] = numbers[numbers[i]];
numbers[temp] = temp;
}
}
return false;
}