2-1众数问题
问题描述
给定含有n个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数。多重集S中重数最大的元素称为众数。
输入
第一行为多重集S中的元素个数n;
第二行为多重集S中的n个元素,每两个元素之间用空格隔开
输出
输出有两行
第一行为众数
第二行为重数
Input
6
1 2 2 2 3 5
Output
2
3
代码及思路
#include<stdio.h>
#define max_size 10
int ans_Zhongshu, ans_Chongshu;
/*计算在起点下标为start,终点下标为end的子序列中中位数的重数;
totalNumber为原数组中数据的个数 */
int Count(int number[],int start,int end,int totalNumber)
{
int midNumber = number[int((start + end) / 2)];
int count = 0;
for (int i = 0;i < totalNumber;i++)
{
if (number[i] == midNumber)
{
count++;
}
}
return count;
}
/*计算在起点下标为start,终点下标为end的子序列中中位数第一次出现的位置;
用以对序列进行进一步的划分*/
int midNumberFirstAppear(int number[],int start,int end,int totalNumber)
{
int midNumber = number[int((start + end) / 2)];
for (int i = 0;i < totalNumber;i++)
{
if (number[i] == midNumber)
{
return i;
}
}
return 0;
}
//在起点下标为start,终点下标为end的子序列中对重数进行递归计算
int Find(int number[], int start, int end, int totalNumber)
{
int midNumberPosition = (start + end) / 2;//计算在起点下标为start,终点下标为end的子序列中中位数的位置
int temp_Chongshu = Count(number, start, end, totalNumber);//计算在起点下标为start,终点下标为end的子序列中中位数的临时重数
int leftPosition = midNumberFirstAppear(number, start, end, totalNumber);//计算在起点下标为start,终点下标为end的子序列中中位数第一次出现的下标位置
if (temp_Chongshu > ans_Chongshu)//如果当前子序列中中位数的重数大于已知重数,则替换已知众数和已知重数
{
ans_Chongshu = temp_Chongshu;
ans_Zhongshu = number[midNumberPosition];
return 0;
}
if (end + 1 - (leftPosition + temp_Chongshu) > ans_Chongshu)//如果中位数第一次出现的位置右侧空余位置大于已知重数,则向右进行递归计算;空余位置大于已知重数,意味着右侧可能出现重数更多的中位数使得该中位数成为新的众数
{
Find(number, leftPosition + temp_Chongshu, end, totalNumber);
}
if (leftPosition > temp_Chongshu)//向左侧递归计算,原理同上
{
Find(number, start, leftPosition, totalNumber);
}
}
int main()
{
int totalNumber, number[max_size];
scanf_s("%d", &totalNumber);
for (int i = 0;i < totalNumber;i++)
{
scanf_s("%d", &number[i]);
}
Find(number, 0, totalNumber - 1, totalNumber);
printf("众数为: %d\n重数为: %d\n", ans_Zhongshu, ans_Chongshu);
return 0;
}