POJ上的一道题目:企业想拥有令人难忘的电话号码。要一个电话号码让人容易记住,方法之一是号码里面有一个难忘的单词或词组拼写。例如,您可以拨打TUT- GLOP拨打沃特卢大学。有时电话号码只有一部分是单词拼写。当你回到你的酒店,今晚你可以通过拨打310 - GINO吉诺订购比萨饼。另一种方法,设计的电话号码是一个难忘的方式分组数字。你可以通过拨打必胜客" 3个10 "的号码3-10-10-10 来订购比萨.
一个电话号码的标准形式是7个十进制数字用连字符之间的第三和第四位数字(如888-1200 ).一个电话的小键盘提供字母数字的映射,如下所示:No duplicates.
采样输入
12
4873279
ITS- EASY
888-4567
3-10-10-10
888 - GLOP
TUT- GLOP
967-11-11
310 - GINO
F101010
888-1200
-4-8-7-3-2-7-9 -
487-3279
样本输出
310-1010 2
487-3279 4
888-4567 3
这道题目解法多种多样,难点在于时间复杂度的控制,花了好长时间在这道题目上,下面说说我的经验;
刚开始我想定义一个数据结构来存储,str字符数组用来存储每一个电话号码(去掉了'-'字符);identy用于存储字符数组的第一个字符,用于排序;icount用来统计每个相同号码的个数,用一个for循环实现起来并不复杂,可是程序一直是TLE(Time Limit Exceeded),查阅了一些资料,不服气自己的程序就是不能通过这道题,一直在修改修改再修改,后来发现,我从一开始就错了,我错的是我把电话号码当成一个字符数组来处理,还创建了结构体来存储,假设有10万个电话号码,还要排序,那时间复杂度就很高了,而且在循环体里面使用了strcmp,strcpy等库函数,花在这上面的时间,灰常多,继续在这上面修改,也不会有多好的效果的,在论坛上得到了大神的启发,转战用数字才存放电话号码,int类型的足矣.
typedef struct { int identy; char str[9]; int icount; }Phone;于是,不采用结构体,直接用整型数组,这样不需要通过什么strcmp,strcpy函数来判断大小和赋值,也能直接用数组存储数据来排序,这样一来,时间复杂度将会大大减小。完整代码是:
#include <stdio.h> #include <stdlib.h> #define MAXSIZE 100000 int cmp(const void *a, const void *b) { int *x = (int *)a; int *y = (int *)b; return (*x) - (*y); } int main() { int cnt = 0; //存放电话号码个数 int iter = 0; int Noduplicates = 0; //有无重复号码的标志,为0则表示无重复 int Sum = 0; int icount = 0; char ch; // 接收键盘输入字符 int *PHONE = (int *)malloc(sizeof(int) * (MAXSIZE + 10)); scanf("%d",&cnt); getchar(); //获取所有电话号码,转换为整型数据 for(iter = 0; iter < cnt; iter++) { Sum = 0; ch = getchar(); while(ch != '\n') { if(ch >= '0' && ch <= '9') { Sum = Sum * 10 + ch - '0' ; } else if(ch >= 'A' && ch <= 'P') { Sum = Sum * 10 + (ch - 65) / 3 + 2 ; } else if(ch >= 'R' && ch <= 'Y') { Sum = Sum * 10 + (ch - 66) / 3 + 2 ; } ch = getchar(); } PHONE[iter] = Sum; } //用快排对电话号码排序 qsort(PHONE, cnt, sizeof(int), cmp); //输出排好顺序的号码 for(iter = 0, icount = 1; iter < cnt - 1 ; iter++) { icount = 1; //统计重复号码个数 while(PHONE[iter] == PHONE[iter + 1]) { iter++; icount++; } if(icount > 1) { Noduplicates = 1; printf("%03d-%04d %d\n",PHONE[iter] / 10000 ,PHONE[iter] % 10000 ,icount); } } if(Noduplicates == 0) { printf("No duplicates.\n"); } getchar(); return 0; }注: Q 和 Z 是不在映射里面的!还有就是输出格式,比如号码"000-0001"不应该输出" - 1"( 前导 0 的问题)