一、问题描述
给定含有n个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数。多重集S中重数最大的元素称为众数。例如,S={1,2,2,2,3,5}。多重集S的众数是2,重数是3。
数据输入: 输入数据由文件名为input.txt的文本文件提供。文件的第1行为多重集S中元素个数n;在接下来的n行中,每行有一个自然数。
结果输出: 将计算结果输出到文件output.txt。输出文件有2行,第1行是众数,第2行是重数。
二、分析
首先先将所有的数组元素从小到大排序,然后将所有元素进行扫描,并从中找到众数的大小和众数的个数。扫描时需要定义两个变量,一个用来记录众数的大小,一个用来记录众数的个数。
在input.txt文本的第一行输入多重集S的元素个数,在接下来的几行中输入集合的元素。
三、运行结果
运行程序后,打开output.txt文本,可知第一行为众数的大小,第二行为重数即该众数的个数。
四、代码
#include <iostream>
#include <algorithm>
#include<fstream>
using namespace std;
#define N 10000
bool cmp(int a, int b) {
return a < b;
}
int MaxNum = 0; //存储众数大小
int MaxNumCount = 0; //存储众数个数
int num[10000];
void split(int left, int right) {
if (left >= right) return;//越界跳出
int FirstLeft = left;//记录初始最左侧
int FirstRight = right;//记录初始最右侧
int mid = (left + right) / 2;
for (; left < mid && num[left] != num[mid]; left++);//找到中位数的左临界
for (; right > mid && num[right] != num[mid]; right--);//找到中位数的右临界
if (MaxNumCount < right - left + 1) { MaxNum = num[mid]; MaxNumCount = right - left + 1; }
//若此中位数个数大于众数个数,则更新
//若中位数左临界左边数字个数小于众数个数,则不需要执行下述操作
if (left - FirstLeft > MaxNumCount)split(FirstLeft, left - 1);
if (FirstRight - right > MaxNumCount)split(right + 1, FirstRight);
}
int main()
{
ifstream in("input.txt");
ofstream out("output.txt");
int n;
in >> n;
for (int i = 0; i < n; i++) {
in >> num[i];
}
sort(num, num + n, cmp);//将数组从小到大排序
int left0 = 0; int right0 = n - 1;
split(left0, right0);
out << MaxNum << endl;
out << MaxNumCount << endl;
in.close();
out.close();
return 0;
}