找出数组中重复的数字
在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复的几次。请找出数组中任意一个重复的数字。
例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出应该是重复的数字2或者3。
解题思路1:哈希法
由于数组里所有数字的范围为0~n-1
,因此,我们可以使用数组里数字的值来进行计算:
- 初始化一个大小为
n
的计数数组 - 遍历数组,将计数数组下标为遍历到元素的值
+1
(如,遍历到1
,计数数组的1
号元素+1
) - 计算数组中值大于
1
的元素对应下标为重复的元素
实现代码如下:
#include <iostream>
using namespace std;
int duplicate(int arr [],int n){
int ha[n]={0};
for(int i=0;i<n;i++)ha[arr[i]]++;
for(int i=0;i<n;i++)
if(ha[i]>1)
return i;
}
int main(){
int arr[]={2,3,1,0,2,5,3};
int n=7;
int ha[n];
cout<<duplicate(arr,n);
}
代码运行结果为:
2
题目中要求输出2
或3
均可,我们只需要输出一个就可以
解题思路2:重排法
重新排序这个数组:
- 从头到尾依次扫描数组中的每个数字,当扫描到下标为
i
的数字时,首先比较这个数字(用m
表示)是不是等于i
- 如果是,则接着扫描下一个数字,如果不是,则再拿它和第
m
个数字进行比较 - 如果它和第
m
个数字相等,就找到了一个重复的数字(该数字在下标为i
和m
的位置都出现了) - 如果它和第
m
个数字不相等,就把第i
个数字和第m
个数字交换,把m
放到属于它的位置。接下来再重复这个比较、交换过程,直到我们发现一个重复的数字
实现代码如下:
#include <iostream>
using namespace std;
int duplicate(int arr [],int n){
int i,temp;
for(i=0;i<n;i++){
while(arr[i]!=i){
if(arr[i]==arr[arr[i]]){
return arr[i];
}
temp=arr[i];
arr[i]=arr[arr[i]];
arr[temp]=temp;
}
}
}
int main(){
int arr[]={2,3,1,0,2,5,3};
int n=7;
int ha[n];
cout<<duplicate(arr,n);;
}
代码运行结果为:
2
《剑指Offer》面试题3