前2种方法很简单,第三种必须要考虑到条件的限制才有可能想到,即数字范围在n-1之内
#include<iostream>
#include<string>
#include<queue>
using namespace std;
/***
***长度为n的数组,里面的数字范围为0-n-1,判断是否有重复的数字
***弄个函数,若有重复数字,返回重复数字,若无则返回-1
***/
//方法1:排序后再扫描
//时间复杂度nlog(n)+n
int duplicate1(int number[],int length)
{
int i;
sort(number,number+length);//递增排序
for(i=0;i<length-1;i++)
{
if(number[i]==number[i+1])
return number[i];
}
return -1;
}
//方法2:哈希表
//时间复杂度n,空间复杂度n
//哈希结构,data为-1时说明还不存在
struct num
{
int data;
struct num *next;
};
#define M 100
struct num *hash[M];
//插入加查询是否有重复数字
int hash_insert(struct num *h,int num)
{
if(h->data==-1)
{
h->data=num;
h->next=new struct num;
h->next->data=-1;
}
else
{
if(h->data==num)
return 1;
else return hash_insert(h->next,num);
}
return 0;
}
#define HASH_KEY 100
int duplicate2(int number[],int len)
{
int i,key;
for(i=0;i<len;i++)
{
hash[i]=new struct num;
hash[i]->data=-1;
}
for(i=0;i<len;i++)
{
key=number[i]%HASH_KEY;
if( hash_insert(hash[key],number[i]) )
return number[i];
}
return -1;
}
//方法3:利用题目特性,长度为n的数组,数字大小在n-1内
//如果没有重复,则排序后相应下标肯定是下标自身
//故用交换方式,比如检测第0个,如果数字是5,就与第五个交换
//直到把数字0交换到0位置上
//如果0位置不是0,是2的话,则下一步肯定再与2交换
//这时候就会发现位置2已经是数字2了,那么就存在重复
int duplicate3(int number[],int len)
{
int i,key,temp,place;
for(i=0;i<len;i++)
{
while(1)
{
if(number[i]==i)
break;
else
{
if(number[i]==number[number[i]])
return number[i];
else
{
place=number[i];
temp=number[i];
number[i]=number[place];
number[place]=temp;
}
}
}
}
return -1;
}
int main()
{
int number[]={2,3,1,0,2,5,3};
int number1[10]={9,8,7,6,5,4,3,2,1,1};
int length=10,dupnum;
dupnum=duplicate3(number1,length);
if(dupnum==-1)
printf("无重复数字!\n");
else printf("重复数字为%d\n",dupnum);
}