判断数组中是否包含重复数字

来源:互联网 发布:保暖内衣选购知乎 编辑:程序博客网 时间:2024/06/10 09:49

给定一个长度为N的数组,其中每个元素的取值范围都是1到N。判断数组中是否有重复的数字。(原数组不必保留)

 

方法1.
对数组进行排序(快速,堆),然后比较相邻的元素是否相同。
时间复杂度为O(nlogn),空间复杂度为O(1)。

方法2.
使用bitmap方法。
定义长度为N/8的char数组,每个bit表示对应数字是否出现过。遍历数组,使用 bitmap对数字是否出现进行统计。
时间复杂度为O(n),空间复杂度为O(n)。

方法3.
遍历数组,假设第 i 个位置的数字为 j ,则通过交换将 j 换到下标为 j 的位置上。直到所有数字都出现在自己对应的下标处,或发生了冲突。
时间复杂度为O(n),空间复杂度为O(1)。

方法3示例代码如下:

bool isUnique(int *X, int N){    for(int i=0; i<N; ++i)    {        if(X[i] != i+1)//X[i]不在自己的位置        {            if(X[X[i]-1] == X[i])return false;            swap(X[i], X[X[i]-1]);        }    }    return true;}

方法4.

××××××××××××××××××××××××××××××××××

固定偏移标志法

 

利用标记法单纯写个O(N)的方法并不难,关键是如何保证两点:

不改变A[]的初始值

函数内不开辟另外的O(N)内存空间.

 

很明显上述方法申请了O(N)内存空间,当N过大时,性能降低了

因此应利用a[N]本身中值和下标的关系来做标记,处理完成后再清除标记即可

 

a[N],里面是1至N-1。原数组a[i]最大是N-1,若a[i]=K在某处出现后,将a[K]加一次N,做标记,当某处a[i]=K再次成立时,查看a[K]即可知道K已经出现过。a[i]在程序中最大也只是N-1+N=2N-1溢出了怎么办啊???),此为一个限制条件

 int do_dup(int arr[],int NUM){    int temp=0;     for(int i=0; i<NUM; i++)    {        if(arr[i]>=NUM)           temp=arr[i]-NUM;            // 该值重复了,因为曾经加过一次了        else            temp=arr[i];         if(arr[temp]<NUM)        {            arr[temp]+=NUM; //做上标记        }        else        {             printf("有重复");                return temp;        }    }     printf("无重复");    return -1;}


上面就是时间复杂度O(N), 空间复杂度O(1)的算法!

 

××××××××××××××××××××××××××××××××××

符号标志法

 

上述方法将元素加一个固定的NUM来做标记,可能会造成溢出。下列方法中利用符号位来做标记,因为1~N都为正值,所以就无限制了。基本思想是用int数组的符号位作哈希表。(反正不是unsigned int符号位闲着也是闲着)

int dup(int array[],int n){     for(int i=0;i<n;i++)     {         if(array[i]>0) //可以以此作下标去判断其他值         {              if(array[array[i]]<0)              {                    return array[i];//已经被标上负值了,有重复              }              else               {                    array[array[i]]= -array[array[i]]; //否则标记为负              }         }         else // |array[i]|代表的值已经出现过一次了         {              if(array[-array[i]]<0)              {                    return -array[i];//有重复              }              else               {                    array[-array[i]]=-array[-array[i]];              }         }     }     return -1;//没有重复}


收集整理自以下两篇博客:

http://hi.baidu.com/nicker2010/item/9cbed11c6811b8707a5f2513

http://www.cnblogs.com/relang99/archive/2008/12/23/1360773.html

0 0