活动地址:CSDN21天学习挑战赛
学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。
题目描述
给定大量手机用户通话记录,找出其中通话次数最多的聊天狂人。
输入格式
输入首先给出正整数N(≤105),为通话记录条数。随后N行,每行给出一条通话记录。简单起见,这里只列出拨出方和接收方的11位数字构成的手机号码,其中以空格分隔。
输出格式
在一行中给出聊天狂人的手机号码及其通话次数,其间以空格分隔。如果这样的人不唯一,则输出狂人中最小的号码及其通话次数,并且附加给出并列狂人的人数。
输入样例
4
13005711862 13588625832
13505711862 13088625832
13588625832 18087925832
15005713862 13588625832
输出样例
13588625832 3
代码长度限制 16 KB 时间限制 600 ms 内存限制 64 MB
来源PTA:https://pintia.cn/problem-sets/15/problems/722
解题代码
#include<bits/stdc++.h>
using namespace std;
struct treeNode{
long long data;
int time;
treeNode *L_child,*R_child;
};
long long ans;
int t,same;
void insertNode(treeNode *&root,long long data)
{
if(root==NULL){
root=new treeNode();
root->time=1;
root->data=data;
root->L_child=root->R_child=NULL;
return;
}
if(root->data>data){
insertNode(root->L_child,data);
}else if(root->data<data){
insertNode(root->R_child,data);
}else{
root->time++;
}
}
void LNR(treeNode *root)
{
if(root==NULL){
return;
}
LNR(root->L_child);
if(root->time>t){
t=root->time;
ans=root->data;
same=1;
}else if(root->time==t){
same++;
}
LNR(root->R_child);
}
int main()
{
int n;
long long a,b;
while(cin>>n)
{
treeNode *root;
root=NULL;
for(int i=0;i<n;i++){
cin>>a>>b;
insertNode(root,a);
insertNode(root,b);
}
ans=t=same=0;
LNR(root);
if(same>1){
printf("%lld %d %d\n",ans,t,same);
}else{
printf("%lld %d\n",ans,t);
}
}
}
解题思路
这道题一开始我看到的时候就想到了散列表,以前写题目遇到电话号码有关的全部都用散列表处理,但是看了一下,要记录次数,然后还要记录次数相同的数量,遍历的时候还要找电话号码小的,那我觉得二叉排序树可能更方便一点,我就用了二叉排序树。后来做完了去百度,发现这道题目的初衷还是散列表,怎么说呢,解题的方法还是很多的。
longlong类型能够表示长度为11位的数字,其实还是比较好做的了,只要根据二叉排序树的原理进行存储就行,最后先序遍历吧,因为小的号码都在左边嘛,其实中序先序后序遍历不影响遍历时间。最后我提交通过后比较了以下别人散列做法提交的时间,多了几十毫秒吧,还是能够实现的。
不会二叉排序树就用map做,红黑树虽然我也还不是很明白,但是STL容器会用其实解题还是够的。散列以后再写。
二叉排序树的代码
别人的散列表