給定含有n個元素的多重集合S,每個元素在S中出現的次數稱爲該元素的重數。多重集S中重數最大的元素爲衆數。例如,S={1,2,2,2,3,5},多重集S的衆數是2,其重數爲3。 對於給定的由n(n<100)個自然數組成的多重集S,計算S的衆數及其重數。
輸入格式:
輸入在一行中給出多重集S中的元素個數n;在接下來的n行中,每行有一個自然數。
輸出格式:
輸出有2行,第1行是衆數,第2行是重數。
輸入樣例:
6
1
2
2
2
3
5
輸出樣例:
2
3
算法思想:
對於這個算法,我們採用分治的思想。我們先給定一個數組a,然後將數組排序,我們找到數組a中位於中間的數及其重數n,如果左邊的元素個數大於n,那麼衆數在左邊可能出現,我向左遞歸,右邊同理。這樣遞歸下去我們就可找到衆數及其重數了。在這裏我們要用到三個函數,分別爲count(用於統計數組中間數出現的次數),start(用於返回當前數組的中間數第一次出現位置的索引),mode(用於找衆數)。
在這裏插入代碼片
#include<iostream>
using namespace std;
int num=0; //定義全局變量n用來存儲衆數
int sum=0; //定義一個全局變量sum用來存儲重數
int count(int a[],int p,int q)
{//定義一個統計數組中間數出現的次數。a爲待統計的集合,參數p爲待遞歸數組第一個數的索引,q爲帶遞歸數組最後一個數的索引
int n=a[(p+q)/2];
int counts=0;
for(int i=p;i<q;i++)
{//從待統計數組的第一個數的索引開始統計,直到q結束
if(a[i]==n)
{
counts++;
}
}
return counts;
}
int start(int a[],int p,int q)
{//定義一個方法,用於返回當前數組的中間數第一次出現位置的索引。參數p爲當前數組第一個數的位置索引,q爲最後一個索引
int x=0;
//從當前數組的第一個數開始,當第一次找到與當前數組的中間數相等的數,跳出循環,並返回i
for(int i=p;i<q;i++)
{
if(a[i]==a[(p+q)/2])
{
x=i;
break;
}
}
return x;
}
void mode(int a[],int p,int q) //剛開始第一步時p=0,q=n
{
int tnum=(p+q)/2; //tnum爲當前數組中間數的索引
int tsum=count(a,p,q); //統計中間數的重數
int left=start(a,p,q); //找到當前數組中間數第一次出現的位置,記錄下來
if(tsum>sum) //如果中間數的重數大於sum,將中間數賦給num
{
sum=tsum;
num=a[tnum];
}
if(q-(left+tsum)>sum) //如果當前數組右邊元素的個數大於重數sum,那麼右邊可能出現衆數,向右遞歸尋找
{
mode(a,left+tsum,q);
}
if(left>sum) //如果當前數組左邊元素的個數大於重數sum,那麼左邊可能出現衆數,向左遞歸尋找
{
mode(a,0,left);
}
}
//主函數
int main()
{ int arr[100]; //定一個100大小的整型數組
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>arr[i];
// arr[i] = n; //賦值1-100的數
}
mode(arr,0,n);
cout<<num<<endl; //衆數
cout<<sum<<endl; //重數
return 0;
}
/*cannot convert from ‘int *’ to ‘int []’
出錯報告說是賦值時發生錯誤,無法將整型數據轉化爲整型指針變量。
你不能把一個對象的值賦給指針,只能將一個對象的地址賦給指針。改成:p=&a[i];
*/