对于n个 0 ~ n-1的数组,查找其中重复的数字。许多面试题类似于这种,而且有些还有附加条件,最后说吧。
刚开始我们可能想到,用一个同样大的数组的下标标识这个数组的每一个元素,而新的数组的值是这个下标在原来数组中出现了多少次。如下:
bool hasTheSameNum(int a[],int length)
{
int*p =new int[length];
for (int i=0;i<length;i++)
{
p[i]=0;
}
for (int i=0;i<length;i++)
{
p[a[i]-1]++;
}
for (int i=0;i<length;i++)
{
if(p[i]>1)
return true;
}
delete []p ;
return false;
}
首先把新的数组置空,然后遍历旧数组,每个数的值都是新数组的小标,然后在统计个数。具体来说是这样的,时间复杂度为o(n),空间复杂度为o(n)。应该还能有一些提升,如果在原来的数组上直接操作呢?
bool hasTheSameNum(int a[],int length)
{
int temp=0,i=0;
if(a==nullptr||length<0)
return false;
for(i=0;i < length;i++){
if(a[i]<0 || a[i]> length-1)
return false;
}
for (i=0;i<length;i++)
{
while (a[i]!=i)
{
if(a[i]==a[a[i]])
return true;
temp=a[i];
a[i]=a[a[i]];
a[a[i]]=temp;
}
}
return false;
}
上面这个算法思路在于我们直接操作原数组,从第一个开始,获取下标为0的数组元素的值,判断这个值是否等于它所在的下标。如果不等,就与下标为这个值的元素互换,比如下标为0的这个元素值为7,所以我们把7与下标为7的元素(比如这个值为10)互换,所以现在在下标为0的元素的值是10,而下标为7的元素的值是7。如果相等,那么就比较下一个,以此类推。最差的情况是没有重复的数字,按照这样互换,我们只需要互换n次就给这个数组排序了(递增)。
这种的算法要比之前的算法好一点,空间上相对于之前少用了n个数组元素大小,时间复杂度同样为o(n),而空间复杂度为o(1)。但是用这种方法的情况在于可以改变数组元素的位置,而上面是没有改变元素位置的,具体用哪一种,可以视情况而定。