众数问题(递归分治)

众数问题(递归分治)

问题描述:
给定含有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
算法思想:

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

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

  • 往右界递归取中位数为众数,个数为重数,比较
    在这里插入图片描述
    注意!!!

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

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

#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;
}

运算结果为:
在这里插入图片描述

  • 31
    点赞
  • 154
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值