1、题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
2、代码1
2.1 原理:特别注意这个题目中的条件设置,数字的长度为N,数组里所有数组的范围是0-(N-1),这是这个题目最根本的条件。那么直接用一个长度为N的辅助数组,存储每个数的出现次数即可,第一个出现次数大于1的就是第一个重复出现的数字。
2.2 代码:
// 可以运行的
class Solution1 {
public:
bool duplicate(int numbers[], int length, int* duplication)
{
if(length<=0 || numbers==NULL)
return false;
bool *p = new bool[length];
memset(p, 0, sizeof(bool)*length);
for(int i=0;i<length;i++)
{
//如果numbers[i]之前出现过
if(p[numbers[i]]==true)
{
*duplication = numbers[i];
return true;
}
//numbers[i]之前没出现过
p[numbers[i]]=true;
}
return false;
}
};
注意:这里用bool存储的原因是只需要检测第一个重复出现数,因为对于每次数,只需要知道在之前这个数有没有出现过。用bool可以节省空间内存。
3、代码2
3.1 原理:
特别注意这个题目中的条件设置,数字的长度为N,数组里所有数组的范围是0-(N-1),也就是说数组的每个值也是数组的某个下标。
3.2实例分析:
那么怎么标志一个数出现过了呢,以下标i的数组元素分析numbes[i]=m,由于数字元素是0-(N-1)的,那么m也是数组元素的下标,即numbers[m]存在,且numbers[m]的值是小于N的,那么只要将numbers[m]+=N,就可以作为m已经出现过的标志了,但是这样不是覆盖了numbers[m]这个元素之前的值了嘛,这个好办,对于每个元素的值,如果其值大于等于N,那么减去N得到的值就是对应元素真实原始的值。后面再来一个元素的值,只需要判断其真实值(大于等于N就减去N得到的数)作为下标对应的元素的值是不是大于等于N即可,即可判别该元素在之前是否出现过。
3.3 代码
class Solution {
public:
bool duplicate(int numbers[], int length, int* duplication)
{
if(length<=0 || numbers==NULL)
return false;
int index=0; //存储每个元素的真实值
for(int i=0;i<length;i++)
{
index = numbers[i];
//计算每个元素的真实值
if(index>=length)
index-=length;
//判断这个元素之前是否出现过
if(numbers[index]>=length)
{
*duplication=index;
return true;
}
//没有出现过,则标识下
numbers[index]+=length;
}
return false;
}
};