在网上看到的多益网络的一道笔试题目。大意如下:
对一个集合A = (1, 5, 6, 5, 5,5, 3, 5 ) 当其中一个数的个数大于或等于(忘记了是不是有等于)所有元素个数总和的一半,则称这个数字为这个集合的主元素。如5为A的主元素。假设在一个一维数组中存储了若干个数字,设计一个算法如果这个一维数组有主元素,则输出来,否则,返回 -1。(要考虑时间复杂度,空间复杂度)。
假设当其中一个数的个数大于或等于所有元素个数总和的一半,则称这个数字为这个集合的主元素。(有等于)
这道题目类似找第k大的数。用快速排序来划分数组,第一次划分后,我们只划分中位数所在的那一段,之后一直这样做,直到找到中位数。因为主元素占了数组至少一半,找到中位数,主元素肯定已经按着了(如有有主元素的话)。之后再扫描一遍即可。
#include <iostream>
using namespace std;
void exchange(int &a,int &b)
{
int tmp=a;
a=b;
b=tmp;
}
int Partition(int *A,int start,int end)
{
int tmp=A[end];
int i=start;
for (int k=start;k<end;k++)
{
if(A[k]<=tmp)
{
exchange(A[k],A[i]);
i++;
}
}
exchange(A[i],A[end]);
return i;
}
void findMain(int *A,int length)
{
int mid=(length+1)/2;
int q=Partition(A,0,length-1);
int s,e;//新的开始和结束点
if (mid<q)
{
s=0;
e=q-1;
}
else
{
s=q+1;
e=length-1;
}
while(mid!=q)
{
if (mid<q)
{
q=Partition(A,s,e);
}
else
{
q=Partition(A,s,e);
}
if(mid<q)
{
e=q-1;
}
else s=q+1;
}
}
int main()
{
int A[]={1,5,6,5,5,5,3,5};
int length=sizeof(A)/sizeof(int);
findMain(A,length);
int MainMember;
int maxleng=0;
int tmp=1;
for (int k=0;k<length;k++)
{
tmp=1;
while(A[k]==A[k+1]&&k<length-2)
{
k++;
tmp++;
}
if (tmp>maxleng)
{
maxleng=tmp;
MainMember=A[k];
}
}
if (maxleng>=(length+1)/2)
{
cout<<MainMember<<endl;
}
else cout<<-1<<endl;
return 0;
}