【2013年408真题】线性表

已知一个整数序列A=(a0,a1,…,an-1),其中0≤ai<n(0≤i<n)。若存在ap1=ap2=…=apm=x且m>n/2(0≤pk<n,1≤k≤m),则称x为A的主元素。例如A=(0,5,5,3,5,7,5,5),则5为主元素;又如A=(0,5,5,3,5,1,5,7),则A中没有主元素。

假设A中的n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A的主元素。若存在主元素,则输出该元素;否则输出-1

【测试样例】{0,5,5,3,5,7,5,5}
【输出结果】5

【测试样例】{0,5,5,3,5,1,5,7}
【输出结果】-1

算法思路一

  1. 选取候选的主元素:依次扫描数组中的数,将第一个遇到的数tmp保存在c中,记录tmp出现的次数为1;继续扫描,若下一个数仍等于tmp,则计数+1,否则计数-1,当计数减到0时,将遇到的下一个整数保存到c中,计数重新记为1,开始新一轮计数,重复上述过程,直到扫描完全部数组元素。
  2. 判断c是否为真正的主元素:再次扫描数组,统计c出现的次数,若大于n/2,则为主元素;否则不存在主元素

上述算法的时间复杂度为O(n),采用空间复杂度为O(1)

​int findMainElem(int R[],int n)
{
    int i,c,count=1;//count为计数工具,记录候选主元素出现的次数
    c=R[0];
    for(i=1;i<n;i++)
        if(R[i]==c)
            count++;
        else
            if(count>0)
                count--;
            else
            {
                c=R[i];
                count=1;
            }
    if(count>0)
        for(i=count=0;i<n;i++)//统计候选主元素实际出现的次数
            if(R[i]==c)
                count++;
    if(count>n/2)
        return c;
    else return -1;
}

算法思路二

  1. 使用快速排序对数组元素进行排序,为减少时间复杂度
  2. 新建标志位统计元素出现的个数,从第1个元素开始遍历数组,若和前一元素相同则标志数组元素在之前基础上+1,若不同,则置为0;其中使用max暂存最大值

上述算法的时间复杂度为O(nlog2n),采用空间复杂度为O(1)

//附加快速排序代码
int Partition(int R[],int low,int high)
{
    int pivot=R[low];
    while(low<high)
    {
        while(low<high&&R[high]>=pivot)
            --high;
        R[low]=R[high];
        while(low<high&&R[low]<=pivot)
            ++low;
        R[high]=R[low];
    }
    R[low]=pivot;
    return low;
}
void QuickSort(int R[],int low,int high)
{
    if(low<high)
    {
        int pivotpos=Partition(R,low,high);
        QuickSort(R,low,pivotpos-1);
        QuickSort(R,pivotpos+1,high);
    }
}
int findMainElem2(int R[],int n)
{
     int i,max,tmp;
     int c=0;
     QuickSort(R,0,n-1);
     int a=R[0];
     for(i=1;i<n;i++)
     {
         if(R[i]!=R[i-1])
         {
             if(max<c)//始终维持max为最大值
             {
                 tmp=R[i-1];//tmp暂存候选主元素的值
                 max=c-1;
             }
              c=0;
         }
         else
         {
             c++;//统计量增加
             max=c;
             tmp=R[i];
         }
     }
     if(max+1>n/2)//由于第一次出现时置为0,所以最终比较结果时需要+1
        return tmp;
    else 
        return -1;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值