题目描述:找出数组中重复的数字
在一个长度为n的数组中,所有数字都在0~n-1的范围内。数组中某些数字是重复的,但是不知道几个数字重复了,也不知道数字重复了几次。请找出数组中所有的重复的数字。例如:一个长度为7的数组{2,3,1,0,2,5,3},数组中重复的数字是2和3。
解法一:排序法。把数组中的数字进行排序,在排序后的数组中扫描。在众多排序算法中,选择快速排序可以比简单选择排序和冒泡排序的时间复杂度低,而且编码也比较简单。采用这种方法的时间复杂度为:O(nlog(n))。
示例代码:
#include <iostream>
using namespace std;
void quicksort(int *a,int left,int right)
{
int i = left, j=right, t;
if (left > right)
{
return;
}
int tmp = a[left];
while(i != j)
{
while (a[j] >= tmp && j > i)
{
j--;
}
if(j > i)
{
a[i] = a[j];//a[i]已经赋值给tmp,a[j]赋值给a[i]之后 ,a[j]留出空位
}
while(a[i] <= tmp && i < j)
{
i++;
}
if(i < j)
{
a[j] = a[i];//此时a[i] 空出来了
}
}
a[i] = tmp;
quicksort(a,left,i-1);
quicksort(a,j+1,right);
}
int main()
{
int a[] = {2,3,1,0,2,2,2,5,3};
quicksort(a,0,8);
for(int i = 0;i < 9; i++)
{
printf("%d ",a[i]);
}
printf("\n");
int flag = 0;
for(int i = 1;i < 9; i++)
{
if(a[i] == a[i+1])
{
flag = 1;
}
else if(flag == 1)
{
printf("%d ",a[i]);
flag = 0;
}
}
printf("\n");
getchar();
return 0;
}
解法二:哈希法。扫描数组中的每个元素,同时把每个元素作为键,元素在数组中出现的次数作为值存储在哈希表中,经过一轮扫描之后,在哈希表中记录了数组中每个元素出现的次数。然后遍历哈希表,即可找出数组中重复的元素。采用这种方法的时间复杂度为O(n),空间复杂度为O(n)。因此,可以认为解法二提高时间复杂度是以牺牲了空间为代价的。
示例代码:
#include <iostream>
#include <map>
using namespace std;
int main()
{
int a[] = {2,3,1,0,2,5,3};
map<int,int> my_map;
for(int i = 0;i < 7; i++)
{
if(my_map.find(a[i]) == my_map.end())
{
my_map[a[i]] = 1;
}
else
{
my_map[a[i]]++;
}
}
for(map<int,int>::iterator iter = my_map.begin();iter != my_map.end();iter++)
{
if(iter->second > 1)
{
printf("%d ",iter->first);
}
}
printf("\n");
getchar();
return 0;
}
解法三:交换法。题中给出的是一个长度为n的数组,数组的下标是0~n-1,数组中的数字也是0~n-1。因此,当数组中不存在重复数字且排序之后,数字i将出现在下标为i的位置。由于数组中存在重复数字,因此,按照上面的思路,存在有的位置没有数字,有的位置要存放多个相同的数字。
根据这种思路,我们可以采用交换法解决这个问题。扫描数组,每扫描一个数字,就比较当前数字是否与其下标相等,若相等,继续向后扫描;若不相等,比较以该数字为下标的元素是否与该元素相等,若相等,说明该元素是一个重复元素,向后扫描,否则,交换该元素和数组中以该元素为下标的元素。
示例代码:
#include <iostream>
using namespace std;
int main()
{
int a[] = {2,3,1,0,2,5,3,2,3};
int t;
for(int i=0;i<9;)
{
if(a[i] != i)
{
if(a[a[i]] == a[i])
{
printf("%d ",a[i]);
i++;
}
else
{
t = a[i];
a[i] = a[a[i]];
a[a[i]] = t;
}
}
else
{
i++;
}
}
return 0;
}
有新想法或者问题欢迎留言。