数组中重复的数字

本文介绍三种查找数组中重复数字的方法:暴力比对O(n^2)、快速排序后比对O(nlogn)及哈希表查找O(n)。通过对比不同算法的时间和空间复杂度,展示如何高效地解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。

参考<<剑指Offer>>一书。

1、当该数组是无序时,遍历该数组,将该数组的每一个元素和它后面的元素作比较,若相同则函数返回。该方法的时间复杂度为O(n^2)。

bool complicatefindduplicate(int *arr,int len,int *duplicate)
{
	if(arr==NULL||len<=0)
		return false;
	for(int ii=0;ii<len;ii++)
		for(int jj=ii+1;jj<len;jj++)
		{
			if(arr[ii]==arr[jj])
			{
				*duplicate=arr[ii];
				return true;
			}
		}
		return false;
}
2、当数组是无序时,可以先利用快速排序法对数组进行排序,然后再分别比较相邻元素是否相同,若相同则函数返回。

//快速排序    分治法
void sortcore(int * arr,int l,int r)
{
	if(l>=r)//递归结束的条件
		return;
	int val=arr[l];//中间值
	int left=l;
	int right=r;
	while(left<right)
	{
		while(left<right&&arr[right]>=val)
			right--;
		if(left<right)
			arr[left++]=arr[right];
		while(left<right&&arr[left]<=val)
			left++;
		if(left<right)
			arr[right--]=arr[left];
	}
	arr[left]=val;
	sortcore(arr,l,left-1);//递归
	sortcore(arr,left+1,r);//递归

}
void sort(int *arr,int len)
{
	if(arr==NULL||len<=0)//判断条件
		return;
	sortcore(arr,0,len-1);
}

bool findduplicate(int *arr,int len,int *duplicate)
{
	if(arr==NULL||len<=0)
		return false;
	sort(arr,len);
	for(int ii=0;ii<len-1;ii++)
	{
		if(arr[ii]==arr[ii+1])
		{
			*duplicate=arr[ii];
			return true;
		}
	}
	return false;
}
3、利用哈希表解决这个问题。从头到尾按顺序扫描数组的每个数,每扫描到一个数字的时候,都可以用O(1)的时间来判断哈希表里是否已经包含了该数字。

如果哈希表里还没有这个数字,就把它加入哈希表中;如果哈希表里已经存在该数字,那么就找到一个重复的数字。这种方法时间复杂度为O(n),空间复杂度为O(n)。

bool hashfindduplicate(int *arr,int len,int *duplicate)
{
	if(arr==NULL||len<=0)
		return false;
	int max=arr[0];
	for(int ii=1;ii<len;ii++)
		if(max<arr[ii])
			max=arr[ii];
	
	int * hash=new int[max+1];
	memset(hash,0,(max+1)*sizeof(int));
	for(int ii=0;ii<len;ii++)
	{
		if(hash[arr[ii]]==0)
		{
			hash[arr[ii]]++;
		}
		else
		{
			*duplicate=arr[ii];
				return true;
		}
	}
	delete hash;
	return false;
}

测试程序

#include<iostream>
using namespace std;
void sort(int *arr,int len);
void mergesort(int *arr,int len);
bool findduplicate(int *arr,int len,int *duplicate);
bool hashfindduplicate(int *arr,int len,int *duplicate);
bool complicatefindduplicate(int *arr,int len,int *duplicate);

void test1()
{
	int numbers[] = {2, 1, 3, 0, 4};
	int duplicate=0;
	if(  findduplicate(numbers,sizeof(numbers)/sizeof(int),&duplicate) )
		cout<<duplicate<<endl;
	else
		cout<<"No duplicate"<<endl;
	if(  hashfindduplicate(numbers,sizeof(numbers)/sizeof(int),&duplicate) )
		cout<<duplicate<<endl;
	else
		cout<<"No duplicate"<<endl;

	if( complicatefindduplicate(numbers,sizeof(numbers)/sizeof(int),&duplicate) )
		cout<<duplicate<<endl;
	else
		cout<<"No duplicate"<<endl;
}
void test2()
{
	int numbers[] = {2, 1, 3, 3, 4};
	int duplicate=0;
	if(  findduplicate(numbers,sizeof(numbers)/sizeof(int),&duplicate) )
		cout<<duplicate<<endl;
	else
		cout<<"No duplicate"<<endl;
	if(  hashfindduplicate(numbers,sizeof(numbers)/sizeof(int),&duplicate) )
		cout<<duplicate<<endl;
	else
		cout<<"No duplicate"<<endl;

	if( complicatefindduplicate(numbers,sizeof(numbers)/sizeof(int),&duplicate) )
		cout<<duplicate<<endl;
	else
		cout<<"No duplicate"<<endl;
}
int main()
{
	test1();
	test2();
	return 0;
}

测试结果:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值