数组站:1.数组中重复的数字

题目

在一个长度为n的数组里的所有数字范围都在0~n-1之间,数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

例如
数组长度为8
数组为:{2,3,4,5,3,2,6,5}
重复数字为3或5

输入情况

1.数组范围在0~n-1,长度为n的数组里包含一个或多个重复数字
2.数组范围在0~n-1,数组中无重复数组
3.数组范围不在0~n-1
3.输入空数组

解决思路:

解决这个问题的办法很多,如:

1.先将数组排序,然后遍历数组,在遍历数组时就可以将元素与后一个元素比较。但是这样做的弊端是会改变我们传入的数组。

2.还可以开辟一个长度为n的数组并初始化为0,由于我们传入的数组范围在0~n之间,所以遍历我们传入的数组,然后在以元素做下标去访问我们新开数组值去做加1操作,然后判断数组中值是否大于2,若是的话,我们就找到了重复的数字。

3.由于题目中长度为n的数组的元素范围为0~n-1,若数组中没有重复数字则排序后数组元素就在其对应下标位置,反之,则不在其对应位置。

思路3续:

下面我继续思路3的完成这道题目,思路是:假设用i表示数组下标,数组名为arr,遍历数组,若数组元素与下标相等则下标加1;反之,持续完成下面操作直到不满足条件,先判断元素与以元素为下标所对应的元素是否相等,若相等则找到了重复元素,若不相等,则将这两个元素的位置进行交换。如下图:

按照上面的思路和前面给的例子,可以得到如下操作顺序【a,b,c,d,e],最后找到重复值2。

程序代码

//返回数组中任意一个重复元素,若数组长度为n,则数组元素范围为0到n-1
//条件:空间复杂度为O(1)
//时间复杂度为O(n)
#include<iostream>
using namespace std;
bool duplicate(int nums[], int len, int* duplication) {
	//判空
	if (nums == nullptr || len <= 0) {
		return false;
	}
	//判断数组元素是否合法
	for (int i = 0; i < len; i++) {
		if (nums[i] < 0 || nums[i] >= len) {
			return false;
		}
	}
	//遍历数组
	for (int i = 0; i < len; i++) {
		//循环交换
		while (nums[i] != i) {
			//找到重复值时
			if (nums[i] == nums[nums[i]]) {
				*duplication = nums[i];
				return true;
			}
			//nums[i]与第nums[i]个数交换,i不++,再比较一次
			/*int temp = nums[i];
			nums[i] = nums[nums[i]];
			nums[nums[i]] = temp;*///不能写成这样,因为nums[i]的值已经改变了
			int temp = nums[i];
			nums[i] = nums[temp];
			nums[temp] = temp;

		}
	}
	//执行完了,就是没找到
	return false;
}

小结:

从上面结果分析知,总时间复杂度为O(n),虽然这种方法不需要额外分配空间,即空间复杂度为O(1),但是数组的结构被改变了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值