题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
思路:我们注意到,数组中的数字都在0到n-1
范围内。如果这个数组中没有重复的数字,那么当数组排序后,数字i
就会出现在索引为i
的位置上。但是现在是数组中有重复的数字,有些位置上可能存在多个数字,有些位置上没有数字。
从头到尾扫描这个数组中的每个数字,当扫描到下标为i
的数字时,首先比较这个数字(记为m
)和下标i
是否相等,若相等,接着扫描下一个数字;若不相等,则将m
与索引为m
上的数字进行比较。如果它与第m
个数字相等,就找到了一个重复的数字;若不相等,则将第i
个数字和第m
个数字交换,把m
放在属于它的位置上。接下来便是重复比较下去,直到发现一个重复的数字。
举例说明:{2,3,1,0,2,5,3}
- 0(索引值)和2(索引值位置的元素)不相等,并且2(索引值位置的元素)和1(以该索引值位置的元素2为索引值的位置的元素)不相等,则交换位置,数组变为:{1,3,2,0,2,5,3};
- 0(索引值)和1(索引值位置的元素)仍然不相等,并且1(索引值位置的元素)和3(以该索引值位置的元素1为索引值的位置的元素)不相等,则交换位置,数组变为:{3,1,2,0,2,5,3};
- 0(索引值)和3(索引值位置的元素)仍然不相等,并且3(索引值位置的元素)和0(以该索引值位置的元素3为索引值的位置的元素)不相等,则交换位置,数组变为:{0,1,2,3,2,5,3};
- 0(索引值)和0(索引值位置的元素)相等,遍历下一个元素;
- 1(索引值)和1(索引值位置的元素)相等,遍历下一个元素;
- 2(索引值)和2(索引值位置的元素)相等,遍历下一个元素;
- 3(索引值)和3(索引值位置的元素)相等,遍历下一个元素;
- 4(索引值)和2(索引值位置的元素)不相等,但是2(索引值位置的元素)和2(以该索引值位置的元素2为索引值的位置的元素)相等,则找到了第一个重复的元素。
#include <iostream>
using namespace std;
class Solution
{
public:
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 true;
}
swap(numbers[i], numbers[numbers[i]]);
}
}
return false;
}
};
int main()
{
int a[] = {2,3,1,0,2,5,3};
Solution b;
int c = 0;
b.duplicate(a, 7, &c);
cout << c << endl;
return 0;
}