【剑指offer】面试题3 数组中重复的数字

1.主旨

  • 考察数组本身的概念,以及在数组中实现对应数的查找。题目本身的含义很容易理解,所以对于这种简单的题目应该多从时间复杂度与空间复杂度这两个角度进行思考,这样才能体现出自己的思想优势。

2.考点

  • 考点1:数组与指针的概念:数组占据着一块连续的内存储存数据,而指针是占着最小内存区间(通常为4B)的存储地址区间的变量。数组的名字为指向数组第一个元素的指针(比如a[2]就是从首元素向后移动三位),同时当数组进行参数传递时会退化成同类型的指针(即当单独使用数组名字时);
  • 考点2:时间复杂度与空间复杂度:这道题的解法多种多样,无非就是这两者有所不同,如何根据面试官的出题来确定自己的思考方向,是其关键;

3.代码

  • 本文使用两种常规方法和一种书上的方法,其中书中的不改变数组时选用的二分查找法本人个人认为无法查找出所有的重复数字,所以暂时未选择实现。

3.1 暴力枚举

  • 简单无脑,看到时最容易想到的方法,两个for循环遍历,直到找到相同数。
  • 时间复杂度O(n2),空间复杂度O(1),牛客网运行时间4ms,内存500K
bool duplicate1(int numbers[], int length, int* duplication) 
{
	for (int i = 0; i < length; i++)
	{
		for (int j = i; j < length; j++)
		{
			if (numbers[i] == numbers[j] && i != j)
			{
				*duplication = numbers[i];
				return true;
			}
		}
	}
	return false;
}

3.2 哈希表(set)

  • 没有必要自己去实现一个哈希表,C++标准库的map与set这两种数据结构足够使用。宗旨为利用set的单一值特性,在不断的insert中找到insert失败的数即可。同时此方法也可以轻易地拓展为找出所有相同的数。
  • 时间复杂度O(n),空间复杂度O(n),牛客网运行时间4ms,内存350K—500K
bool duplicate2(int numbers[], int length, int* duplication)
{
	set<int> number;
	for (int i = 0; i < length; i++)
	{
		auto temp = number.insert(numbers[i]);
		if (!temp.second)
		{
			*duplication = numbers[i];
			return true;
		}
	}
	return false;
}

3.3 下标对比法(书上的方法)

  • 通过假设“对应的数值应该位于对应的下标”,遍历全数组,将当前数据不断地和其对应下标上的数据进行对比,从而找到重复值。
  • 时间复杂度O(n),空间复杂度O(1),牛客网时间4ms,内存600K(从这里来看,反而没有3.2的哈希表好用哈哈)

bool duplicate2(int numbers[], int length, int* duplication)
{
	//1.保护数组为空或长度输入错误时
	if (numbers == nullptr || length <= 0)
		return false;
	//2.保护数组中的数据不符合题目条件,值小于0或大于n-1时
	for (int i = 0; i < length; i++)
		if (numbers[i] < 0 || numbers[i]>length - 1)
			return false;
	//3.正式的下标对比法流程,遍历数组中的所有数据
	for (int i = 0; i < length; i++)
	{
		//3.1 当前数据不等于对应其所处的位置时,进行进一步判断
		while (numbers[i] != i)
		{
			//3.2 当不处于自身位置的数据,与处于自身位置的数据相等,则表示有两个数相等
			if (numbers[i] == numbers[numbers[i]])
			{
				*duplication = numbers[i];
				return true;
			}
			//3.3 如果不等于,则将当前的数据换到属于其自己的位置上去
			else
			{
				swap(numbers[i], numbers[numbers[i]]);
			}
		}
	}
	return false;
}

3.4 二分查找法(书上的方法)

  • 基本思路为选取中心数,不断地将当前区间的数与中心数对比,如果中心数小于某段的数字数目,则表示那个区段存在重复数,而重复数的查找则就是在这其中进行不断地二分的过程。
  • 时间复杂度O(nlogn),空间复杂度O(1),具体没实现所以不知道牛客网跑的效果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方寸间沧海桑田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值