简单找众数算法详解

众数的定义:

是一组数据中出现次数最多的数值,叫众数,有时众数在一组数中有好几个。用M表示。 理性理解:简单的说,就是一组数据中占比例最多的那个数。

例题:

剧中比赛全球大学生都参加了编号从-10^9到10^9,不要问我比赛场地能不能坐下,这是全球同步比赛,结果汇总在一起的。总共题目数可达10万道。给你题目数N,和N个编号,每个编号是指这道题目第一个做出来的参赛者编号,求出出现次数最多的编号和次数,次数相同输出编号最小的。具体格式见样例。

Input

 输入包括多组测试数据

每组测试数据的第一行是一个数字n表示题目数(0<n<=100000)
然后是n个整数表示第一次做出题目的参赛者编号,每个编号在[-10^9,10^9]内

Output

 对于每组测试数据输出2个数,分别表示出现最多次的数和它出现的次数。(如果有多个同样次数的数,输出最小的那个)

Sample Input

5
1 2 1 2 3

Sample Output

1 2
很明显,这是一道在有限数组里面找众数的习题,由于数的范围过大,因此不能用“桶的思想”解决这道试题。

但是我们可以想到,众数以及这个数出现的次数是一一对应的,那么这时候我们就可以想到用一个结构体来存储这个一一对应的关系,如下:

struct node
{
    ll value;
    int length;
};

其中value为数组中的某个数,而length为该数在数组中出现的次数。

这样的话,为了减少重复遍历的次数,我们可以先将数组升序排序,然后只需遍历一遍数组,就可以记录每个数字出现的次数,通过不断变化记录的标志而更新结构体数组的值。我们可以采取如下的方式:

sort(num,num+n);
ll flag = num[0],j = 0,temp = 0,max_num = num[n-1],i;   //flag作为记录的标志
for(i = 0; i < n; i++)
{
     if(num[i]!=flag)
    {
         flag = num[i];
         ans[j].value = num[i-1];
         ans[j].length = i - temp;
         temp = i;
         j++;
     }
}
ans[j].value = num[i-1];
ans[j].length = i - temp;

这里需要注意的一个问题是,由于遍历到最后一个数无法再进行if判断便跳出循环,所以我们无法记录最后一个数字或者说是最后出现的数字的次数,所以在循环体外还要记录一下最后出现的数字的次数。然后当所有数字记录完毕时,再将结构体数组按照数字出现的次数降序排序即可,如果数字出现的次数相同,则将更小的那个数排在前面。因此得出完整代码如下:

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef struct node Node;
const int maxn = 1e5;
struct node
{
    ll value;
    int length;
};
ll num[maxn+10];
bool cmp(Node a,Node b);
int main()
{
    int n;
    while(scanf("%d",&n)==1 && n)
    {
        Node ans[maxn+10];
        for(int i = 0; i < n; i++)
            scanf("%lld",&num[i]);
        sort(num,num+n);
        ll flag = num[0],j = 0,temp = 0,max_num = num[n-1],i;   //flag作为记录的标志
        for(i = 0; i < n; i++)
        {
            if(num[i]!=flag)
            {
                flag = num[i];
                ans[j].value = num[i-1];
                ans[j].length = i - temp;
                temp = i;
                j++;
            }
        }
        ans[j].value = num[i-1];
        ans[j].length = i - temp;
        sort(ans,ans+j+1,cmp);
        printf("%lld %d\n",ans[0].value,ans[0].length);
    }
    return 0;
}
bool cmp(Node a,Node b)
{
    if(a.length == b.length)
    {
        return a.value < b.value;
    }
    else
        return a.length > b.length;
}

时间及内存花费:

Time:73 ms

 Memory:3320 kb

如有错误,还请指正,O(∩_∩)O谢谢



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值