题目来自于剑指offer:在一个长度为n的数组里,所有的数字都在n-1的范围内。数组中某些数字是重复的,也不知道每个数组重复了几次。找出数组中任意一个重复的数字。例如输入{2,3,1,0,2,5,3},那么对应的输出是2或者3.
分析:首先可以牺牲o(n)的空间,通过时间复杂度为o(n)的遍历来实现这道题:具体是定义一个长度为n的数组并初始化为0,通过遍历输入序列的每一个元素,将元素的值操作新定义的:数组【元素值】+1,这样子能求出所有重复的数字,并且还能求出重复的次数。
但是题目中只是要求找出其中一个重复的数字:重排数组,记录下标为i,比较当前下标是不是等于下标的元素(记为m):numberSerial[i] == i ?,如果是,接着扫描下一个。如果不是,那它numberSerial[i] 与第m个元素比较(numberSerial【numberSerial[i] 】),如果不想等,将它们进行交换。反复操作,知道找到一个重复的数字。
因为每个数字最多交换两次就能找到属于它自己的位置,因此时间复杂度是O(n).
以下是代码:
#include "pch.h"
#include <iostream>
#include<vector>
using namespace std;
bool duplicate(vector<int> numberSerial, int length, int *duplication)
{
if (numberSerial.size() <= 0)
return false;
for (int i = 0; i < length; i++)
{
if (numberSerial[i]<0 || numberSerial[i] > length - 1)
return false;
}
for (int i = 0; i < length; i++)
{
while (numberSerial[i] != i)//首先比较是不是
{
if (numberSerial[i] == numberSerial[numberSerial[i]])//如果不是:拿它
{
*duplication = numberSerial[i];
return true;
}
int tmp;
tmp = numberSerial[i];
numberSerial[i] = numberSerial[numberSerial[i]];
numberSerial[tmp] = tmp;
}
}
return false;
}
int main()
{
vector<int> a= {2,3,1,0,2,5,3};
int num;
duplicate(a,a.size(),&num);
cout << num << endl;
std::cout << "Hello World!\n";
}