找数组中的重复数字

在长度为n+1的数组中,由于所有数字都在1到n范围内,存在重复数字。本文介绍了三种不修改原数组的解法:二分查找法,通过不断划分区间来定位重复数字;修改数组顺序,通过交换使每个数字归位,找到重复元素;以及使用哈希表,以O(1)时间复杂度检查并记录每个数字,找出重复项。

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

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

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

  • 二分查找法: 如:{2,3,5,4,3,2,6,7} 先二分,先统计在1-4里面的数字个数,如果大于4则说明1-4里面有重复数字,否则重复数字必然在5-7里面,再对区间进行划分,直到剩一个数字且该数字出现的次数大于一,则该数字就是那个重复数字。
    代码实现
#include<stdio.h>

int getDuplicate(const int* numbers, int length)
{
	if (numbers == NULL || 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 == NULL)
	{
		return 0;
	}

	int count = 0;
	for (int i = 0; i < length; i++)
	{
		if (numbers[i] >= start && numbers[i] <= end)
		{
			++count;
		}
	}
	return count;
}

修改数组的顺序解法

思路:由于长度为n的空间中的元素都在1-n-1之间,因此一个萝卜一个坑.如果数组中没有重复的数字,则第i位置应该放置的数字为i。可以重排此数组,让对应位置上的数字对应。

  • 首先判断元素是否和对应下标相等,如果相等,代表它在自己的正确位置上,不用考虑,直接判断下一个元素
  • 如果不相等,说明它不在自己的位置上,此时它就有可能是哪个重复的元素,此时 分两种情况
  • 情况一:如果 它和自己对应下标下的元素相等就代表它是重复元素
  • 情况二:它还未回到自己的位置上去, 和它应该所在位置的元素进行交换,让它回到自己的位置上去
int duplicate(int *arr,int len)
{
    if(len<0||arr==NULL)
	{
		return -1;
	}
	for(int i=0;i<len;++i)//检查输入数组的合法性
	{
		if(arr[i]<0||arr[i]>=len)
		{
			return -1;
		}
	}
   for(int i=0;i<len;++i)
   {
	 while(i!=arr[i])
	 {
	    if(arr[i]==arr[arr[i]])
		{
			return arr[i];
		}
		int tmp=arr[i];
		arr[i]=arr[tmp];
		arr[tmp]=tmp;
	 }
   }
   return -1;
}

以下几种方法空间复杂读或者时间复杂度都优点高,就不进行代码展示,读者可以通过阅读思路,简单了解一下。O(∩_∩)O

哈希表法

思路:从头到尾顺序扫描数组中的每一个数,每扫描一个数字可以用O(1)的时间在哈希表中判断是否包含此数字,如果哈希表中没有此数字就将此数字加入到哈希表中,如果哈希表中已存在此数字就找到了重复的数字。时间复杂度为O(n),但是空间复杂度也为O(n),以空间换区时间。

排序

思路:将输入的数组进行排序,遍历排序后的数组找到重复的数字(该元素和其下一个元素相等就代表该元素是重复元素)。排序一个长度为n的数字的时间复杂度为O(nlogn),所以这种方法的时间复杂度为O(nlogn)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值