问题链接:ZOJ1159 UVA755 UVALive5420 487-3279
问题简述:为了好记电话号码,将字母映射为数字,人们就可以记忆字母了。给定若干的电话号码,如果没有重复就不输出,如果有重复则输出电话号码及重复次数。如果没有一个电话号码是重复的,则输出“No duplicates”。
问题分析:这个问题的关键是用什么样的数据结构存储有关的信息。需要找到最简洁的字母转换数字的方式,电话号码的存储方式。
程序说明:这个问题与参考链接的问题是同一问题,只是输入输出形式不同。
题记:(略)
Sample Input
1
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
Sample Output
310-1010 2
487-3279 4
888-4567 3
大致思路:
输入形式以字符串来存储,每输入一个字符串,就对其中每个字符进行isdigit和isupper的判断(这样直接就不对'-'处理,忽略'-'),其中,upper的处理用了“查表”方法。然后用一个num巧妙地把该字符串转换成一个整数,并存储入最终需要的整数数组ans中。
然后要对ans进行sort排序(这样的话就可以方便“找重复”的计数),然后依次前后进行对比即可,重复则count++。直到有不同的且count>1则输出之前的重复序列,并重新将count置为1。这样的话就要考虑在遍历完成后再去输入count>1的序列。如果遍历结束后count=1,且flag==0(没有进入过重复的if语句),则no duplicates.
- /* ZOJ1159 UVA755 UVALive5420 487-3279 */
- #include <iostream>
- #include <algorithm>
- #include <stdio.h>
- #include <ctype.h>
- using namespace std;
- int convert[] =
- {
- 2, 2, 2,
- 3, 3, 3,
- 4, 4, 4,
- 5, 5, 5,
- 6, 6, 6,
- 7, 0, 7, 7,
- 8, 8, 8,
- 9, 9, 9,
- 0
- };
- const int N = 128;
- char s[N];
- const int N2 = 100000;
- int ans[N2], acount;
- int main()
- {
- int t, n, num;
- bool tflag = false;
- scanf("%d", &t);
- while(t--) {
- if(tflag)
- printf("\n");
- tflag = true;
- scanf("%d", &n);
- for(int k=0; k<n; k++) {
- scanf("%s", s);
- num = 0;
- for(int i=0; s[i]; i++) {
- if(isdigit(s[i])) {
- num *= 10;
- num += s[i] - '0';
- } else if(isupper(s[i])) {
- num *= 10;
- num += convert[s[i] - 'A'];
- }
- }
- ans[k] = num;
- }
- sort(ans, ans + n);
- bool flag = true;
- int count = 1;
- for(int i=1; i<n; i++) {
- if(ans[i] == ans[i - 1])
- count++;
- else {
- if(count > 1) {
- printf("%03d-%04d %d\n", ans[i - 1] / 10000, ans[i - 1] % 10000, count);
- flag = false;
- }
- count = 1;
- }
- }
- if(count > 1) {
- printf("%03d-%04d %d\n", ans[n - 1] / 10000, ans[n - 1] % 10000, count);
- flag = false;
- }
- if(flag)
- printf("No duplicates.\n");
- }
- return 0;
- }
学到的点:
①查表法——尤其是字母与数字间的转换
②isdigit和isupper函数的运用
③num*10的运用——将一个字符串转成一个数字
③数组排序——找重复时先排好序,这样就可以直接依次前后比较了。