一个大小为N的数组,里面是N个整数,怎样去除重复的数

本文转自:http://blog.csdn.net/jirongzi_cs2011/article/details/11626207

题目:一个大小为N的数组,里面是N个整数,怎样去除重复的数字;

要求时间复杂度为O(n),空间复杂度为O(1). 

 需要除掉重复的整数的数组,注意这里我没有处理负数情况,其实负数情况只要先用0快排分一下组,然后各自用以下算法进行处理即可。 另外因为是整数,这里没考虑32位符号位,只考虑31位。

题目分析:从要求来看,如果一个数组是排好序的,除掉重复就很简单,因此就转换成了排序算法寻找,这种算法需要满足:线性时间,常量内存,原地置换。但纵观这么多算法,比较排序肯定不行,那么就只有基数排序,桶排序和计数排序,计数排序排除,因为计数排序无法原地置换,桶排序也需要辅助空间,所以最后考虑用 基数排序,基数排序依赖于位排序,而且要求位排序是稳定的, 且不能过多使用辅助空间,这里问题是如何选择位排序,因为位上只有0和1,因此有其特殊性,使用快排的分组就可以达到线性,但问题是这种算法虽然是线性,原地置换,但不稳定。所以要利用一种机制来确保快排是稳定的。经过一段时间思考,发现,如果从高位开始排序,假设前K位是排好的,对K+1进行排序时,只针对前K位的相同的进行,前K位不相同,也不可能相等,第K+1位也不影响结果,而前K位相同的排序,就不怕快排的不稳定了,因为这个不稳定不会影响到最终结果。

#include<iostream>
using namespace std;
bool isbitof1(int num,int index);//判断num的index位是否为1,index从0开始
void partition_m(int data[],int start,int end,int index,bool (*cond)(int,int));//分割函数
void linear_sort(int data[],int n);//线性排序,基于基数排序,关键字为某位二进制位是0还是1,一共32位
int delete_repeated(int data[],int n);
int main()
{
    int N;//数组元素个数
    cin>>N;//用户输入
    int *data=new int[N];
    int i;
    for(i=0;i<N;i++)
        cin>>data[i];//输入数组元素
    int len=delete_repeated(data,N);
    for(i=0;i<len;i++)
        cout<<data[i]<<" ";
    cout<<endl;
    return 0;
}
bool isbitof1(int num,int index)
{
    num=(num>>=index)&1;//判断index位是零还是1
    if(num==1)
        return true;
    else
        return false;
}
void partition_m(int data[],int start,int end,int index,bool(*cond)(int,int))
{
    if(data==NULL||start>end)
        return;
    int i=start-1;
    int j=end+1;
    while(true)
    {
        do
        {
            i++;
        }while(!cond(data[i],index)&&i<=end);
        do
        {
            j--;
        }while(cond(data[j],index)&&j>=start);
        if(i>j)
            break;
        int temp=data[i];
        data[i]=data[j];
        data[j]=temp;
    }
}
void linear_sort(int data[],int n)
{
    if(data==NULL||n<=0)
        return;
    int indexofbit,i,processed_bit;
    //从高位到低位
    for(indexofbit=30;indexofbit>=0;indexofbit--)
    {
        int start=0;
        int end=0;
        int prev=(data[0]>>(indexofbit+1))&(0x7FFFFFFF);
        for(i=0;i<n;i++)
        {
            processed_bit=(data[i]>>(indexofbit+1))&(0x7FFFFFFF);
            if(processed_bit==prev)
                end=i;
            else
            {
                partition_m(data,start,end,indexofbit,isbitof1);
                prev=(data[i]>>(indexofbit+1))&(0X7FFFFFFF);
                start=i;
                end=i;
            }
            
        }
        partition_m(data,start,end,indexofbit,isbitof1);
    }
}
int delete_repeated(int data[],int n)
{
    linear_sort(data,n);
    int i,j;
    i=0;
    j=i+1;
    while(j<n)
    {
        if(data[j]!=data[i])
        {
            i++;
            data[i]=data[j];
            j++;
        }
        else
        {
            j++;
        }
    }
    return i+1;
}

 

时间复杂度为O(31*n)=O(n),空间复杂度为O(1),有问题欢迎评论指正,大家一起学习讨论。

 

posted @ 2014-04-25 22:17  燃烧吧,少年  阅读(678)  评论(0编辑  收藏  举报