题目一、找出数组中重复的数字
在一个长度为n的数组里的所有数字都在0~n-1的范围内。
数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了多少次。请找出数组中任意一个重复的数字。
例如,如果长度为7 的数组{2,3,1,0,5,3},那么对应的输出是重复的数字2或3。
该题还可用哈希表或者排序解决
关键点:
- 异常处理
- const规范
代码:
#include <iostream>
using namespace std;
bool duplicate(const int nums[], const int length, int& duplication) {
//异常处理
if (nums == nullptr || length <= 0) {
return false;
}
for (int i = 0; i < length; i++) {
if (nums[i]<0 || nums[i]>length - 1)return false;
while (nums[i]!=i)
{
if (nums[i] == nums[nums[i]]) {
duplication = nums[i];
return true;
}
int temp = nums[i];
nums[i] = nums[nums[i]];
nums[temp] = temp;
}
}
return false;
}
int main()
{
int a[] = { 0,1,3,3 };
int dup = -1;
cout << duplicate(a, 4, dup) << dup;
}
题目二、不修改数组找出重复的数字
比起上面的题目添加一个要求
不修改数组!
可以使用辅助数组判断
时间复杂度:O(n)
空间复杂度:O(n)
以时间换空间的算法:
#include <iostream>
using namespace std;
bool duplicate(int nums[], int length, int& duplication) {
//异常处理
if (nums == nullptr || length <= 0) {
return false;
}
int start = 1;
int end = length - 1;
for (int i = 0; i < length; i++) {
int mid = ((end - start) >> 1) + start; // (start+end)/2 防溢出
int count = 0;
for (int j = 0; j < length; j++)
if (nums[j] >= start && nums[j] <= mid) count++;
if (start == end)
{
if (count > 1) {
duplication = nums[start];
return true;
}
else return false;
}
if (count<=mid-start+1) start = mid + 1;
else end = mid;
}
return false;
}
int main()
{
int a[] = { 0,1,3,3 };
int dup = -1;
cout << duplicate(a, 4, dup) << dup;
}
每次都查找前半段
如果次数多就在前面,否则在后面