问题描述
问题描述
给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人。
输入格式
输入首先给出正整数N(≤105),为通话记录条数。随后N行,每行给出一条通话记录。简单起见,这里只列出拨出方和接收方的11位数字构成的手机号码,其中以空格分隔。
输出格式
在一行中给出聊天狂人的手机号码及其通话次数,其间以空格分隔。如果这样的人不唯一,则输出狂人中最小的号码及其通话次数,并且附加给出并列狂人的人数。
输入样例
4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832
输出样例
13588625832 3
解题思路
本题为统计每个电话号码出现的次数,并且输出出现最多的那个号码和出现次数,如果这样的号码不唯一,输出一共有多少个并列。
一开始我使用了结构体,存储出现的号码和次数,在存储完毕后按照出现次数和号码字典序进行排序。那么第一个号码一定是要求输出的号码和次数,如果下一个的号码出现次数与这个相等,说明有并列,直到不相等时,输出并列个数。结构体计算容易导致超时,最后一个测试点没有通过。代码如下:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
struct per
{
string num;
int count=0;
};
bool cmp(per a,per b)
{
if(a.count!=b.count) return a.count>b.count;
else return a.num<b.num;
}
int main()
{
int n;
cin>>n;
string str1;
vector<per> v;
per no;
int pp=1;
for(int i=0;i<n;i++)
{
int c=2;
while(c--)
{
cin>>str1;
bool flag=0;
int j;
for(j=0;j<v.size();j++)
if(v[j].num==str1)
{
v[j].count++;
flag=1;
}
if(flag==0)
{
no.num=str1;
no.count=1;
v.push_back(no);
}
}
}
sort(v.begin(),v.end(),cmp);
cout<<v[0].num<<" "<<v[0].count;
for(int i=1;i<v.size();i++)
{
if(v[i].count==v[i-1].count)
pp++;
else{
if(pp!=1) cout<<" "<<pp;
break;
}
}
return 0;
}
题目中的关键字为电话号码,值为出现次数。应该使用map计数。在输入号码的同时计算出出现最多次的次数,最后遍历map,因为map默认对key值进行从小到大的排序,因此第一个出现的value值为最大值的号码一定为题目要求的号码,并对最大值统计出现次数。
解题代码
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main()
{
int n,mmax=0;
cin>>n;
string s;
string maxs;
map<string ,int> m;
for(int i=0;i<2*n;i++)
{
cin>>s;
m[s]++;
if(mmax<m[s])
mmax=m[s];
}
map<string,int> ::iterator it;
int cnt=0;
//map默认为key值从小到大排序 ,所以第一个最多电话的人就是号码最小的人
for(it=m.begin();it!=m.end();it++)
if(it->second==mmax)
{
cnt++;
if(maxs=="")maxs=it->first;
}
cout<<maxs<<" "<<mmax;
if(cnt!=1) cout<<" "<<cnt;
return 0;
}