不修改数组找出重复的数字

在长度为n+1的数组中,所有数字范围是1~n,存在至少一个重复数字。通过类似二分法策略,不改变数组,找出重复的数字。虽然能定位到重复数字,但无法保证找到所有重复项。时间复杂度为O(Nlogn),空间复杂度为O(1)。注意面试时需明确面试官的需求。

题目:

   在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7,},那么对应的输出是重复的数字2或者3.

 

这一题貌似和上一种办法差不多,但是不能修改数组,

对于上一种办法的前三种都ok,都可以用,但是第四种办法不能用。

在这里我们就不说前三种。

 

我们把从1~n的数字从中间的数字m分为两部分,前面一半为1~m,后面一半为m+1~n。如果1~m的数字的数目超过m,那么这一半的区域里一定包含重复的数字;否则,另一半m+1~n的区间里一定包含重复的数字,我们可以继续接着一分为二,直到找到一个重复的数字,这种方法类似于二分法,只是多一步统计区间里的数字数目。

Eg:

 

  

int getDuplication(const int *numbers,int length)
{
	if(numbers==nullptr||length<=0)
	 return -1;
	
	int start=1;
	int end=length-1;
	while(end>=start)
	{
		int middle =((end-start)>>1)+start;
		int count =countRange(numbers.length,start,middle);
		if(end == start)
		{
			if(count >1)
			   return start;
			else 
			   break;
		}
		if(count>(middle-start +1))
		    end=middle;
		else
		    start=middle+1;
	}
		return -1;
}

int countRange (const int *numbers;int length;int start,int end)
{
	if(numbers ==nullptr)
	     return 0;
	int count=0;
	if(int i=0;i<length;i++)
	    if(numbers[i]>=start&&numbers[i]<=end)
	       ++count;
	return  count;
}

时间复杂度O(Nlogn)   空间复杂度O(1)

 

 

重点在这,对于上面的这个实例,我们可以找到3,但是不能找到2,因为1~2正好有两个,所以这种算法不能找到每一个重复的数字,在我们面试的时候,要考虑好面试官的要求是什么。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值