众数问题(递归分治)

众数问题(递归分治)

问题描述:
给定含有n个元素的多重集合s,每个元素在S中出现的次数称为该元素的重数。多重集S中重数最大的元素称为众数。例如, S-(1, 2, 2, 2, 3, 3, 5).多重集S的众数是2,其重数为3,对于给定的由n个自然数组成的多重集s,计算S的众数及其重数。如果出现多个众数,请输出最小的那个。
输入数据的第1行是多重集S中元素个数n (n<1 300000) ;接下来的n行中,每行有一个最多含有5位数字的自然数。输出数据的第1行给出众数,第2行是重数。
样例为:
Sample input
6
1
2
2
2
3
5
Sample output
2
3
算法思想:

  • 取中位数的个数为重数,中位数为众数,确定左界、右界。

  • 在往左界递归取中位数为众数,个数为重数,比较

  • 往右界递归取中位数为众数,个数为重数,比较
    众数问题(递归分治)_第1张图片
    注意!!!

  • 如果中位数的个数大于左界个数,那左边一定没有该组数据的众数;反之,右边一样。

  • 该程序要求数据有序(从小到大),本程序未写排序算法。

#include "stdio.h"
#include "stdlib.h"
# define N 100
void Split(int a[],int n,int &l,int &r)
{//以中间数字为界,确定左右界
	int mid = n/2;
	for(l = 0;l <= mid;++l)//找左界
		if(a[l] == a[mid])
			break;//此时l为左界
	for(r = mid + 1;r < n;++r)//找右界
		if(a[r] !=a[mid])
			break;//此时r为右界
}
void getMaxNum(int &num,int &maxnum,int a[],int n)
{//求众数和重数
	int l,r,s;
	int mid = n/2;
	Split(a,n,l,r);
	s = r - l;
	if(s > maxnum)
	{//如果中间数字的个数大于现在的重数,则更新
		num = a[mid];
		maxnum = s;
	}
	if(s == maxnum)//如果出现多个众数,输出最小的那个
	    if(num > a[mid])
		{
			num = a[mid];
		    maxnum = s;
		}
	if(l+1 > maxnum)
	//如果左边的个数>maxnum,则搜索左边
		getMaxNum(num,maxnum,a,l+1);
	if(n - r > maxnum)
	//如果右边的个数>maxnum,则搜索右边
		getMaxNum(num,maxnum,a+r,n-r);
}
int main()
{
	int i,n,a[N];
	int num = 0;//num为众数
	int maxnum = 0;//maxnum为重数
	scanf("%d",&n);//输入数据个数
	for(i = 0;i < n;i++)
	    scanf("%d",&a[i]);//输入数据
	    //sort(a[i]);//将数据排序
	getMaxNum(num,maxnum,a,n);
	printf("%d\n%d",num,maxnum);
	return 0;
}

运算结果为:
众数问题(递归分治)_第2张图片

你可能感兴趣的:(算法设计与分析)