实验总结
刚开始我没有想到可以用分治法来做,用的是数组来做。做完以后发现算法太过复杂,而且处理较大的n时,时间复杂度和空间复杂度都比较大。于是我参考了算法答案那本书,学到了分治法来解决这道题。但是在完成了用分治法的代码以后,我发现了问题:
输出应该为:
2
4
分治法解决这道题有一个大前提:多重集中的元素是有序的(递增或者递减),所以很有必要给多重集加入一个排序的算法.
附录:(要求代码里各行要有注释)
自己的代码(性能不够好,太过复杂)
int main()
{
int n;
cin>>n;
int a[n];
for(int i=0;i
{
cin>>a[i];
}
f(n,a);
return 0;
}
void f(int n,int *a)//n为多重集元素的个数,a是存放数组的元素
{
int b[n][2];//b[][0]存放元素的种类,B[][1]存放每种元素的个数
b[0][0]=a[0];
b[0][1]=1;
int h=0;//数组b中已初始化的行的标号
int flag=0;//判断b中是否已经有该元素了
for(int i=1;i
{
for(int j=0;j<=h;j++)
{
if(a[i]==b[j][0])//判断元素a[i]是否已经在数组b中存在
{
b[j][1]++;
flag=1;
}
}//存在的话,把b[j][1]加1,flag变为1,否则不做操作
if(flag==0)
{
h++;
b[h][0]=a[i];
b[h][1]=1;
}
flag=0;
}//不存在的话,flag为0,此时把a[i]加入到数组之中,并把个数变为1
int temp=b[0][1];
int t=0;
for(int i=0;i<=h;i++)//寻找b中数目最多的那个元素
{
if(temp
{
temp=b[i][1];
t=i;
}
}
cout<
}
参照答案和csdn博客所改的代码:
int main()
{
int n;
cin>>n;//元素个数
int a[n];
for(int i=0;i
{
cin>>a[i];
}//数组用于存放元素
int l=0;//数组的首个标号
int r=n-1;//数组的最后一个标号
int largest=0;//重数的初始化
int elem=-1;//众数的初始化
mode(a,l,r,largest,elem);//调用函数
cout<
return 0;
}
//用于求数组的中位数的函数↓
int median(int *a,int l,int r)
{
return a[(l+r)/2];
}
//以med来划分数组↓ !!!关键函数
void split(int *a,int med,int l,int r,int &l1,int &r1)
{
for(l1=l;l1<=r;l1++)
{
if(a[l1]==med)
break;
}//l1表示首个等于med的数组下标
for(r1=l1+1;r1<=r;r1++)
{
if(a[r1]!=med)
break;
}
r1--;
}//r1表示最后一个等于med的数组下标
void mode(int *a,int l,int r,int &largest,int &elem)
{
int l1,r1;//分割后左边子数组的右界和右边子数组的左界
int med=median(a,l,r);//midian函数用于找到数组的中位数
split(a,med,l,r,l1,r1);//以med中位数来分割数组
if(largest
{
largest=r1-l1+1;
elem=med;
}//每次递归更新众数和重数的值
if(l1-l>largest)
mode(a,l,l1-1,largest,elem);//判断左边是否值得递归(只有l1-1大于largest才有必要搜寻)
if(r-r1>largest)
mode(a,r1+1,r,largest,elem);//判断右边是否值得递归
}