UVa_OJ 755 487-3279

本文介绍了一种算法,用于将易于记忆的字符串形式电话号码转换为标准数字形式,并检查重复号码。讨论了优化技巧,包括使用ASCII码映射和整数存储以提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题的大意是这样的:

为了能够容易记住电话号码,人们经常把电话号码按某种方式进行记忆,如:把 310-1010记为“three tens”。现在给你一个字符串集,其中包含多个容易记忆的电话号码的字符串,现在需要你判断给定的字符串集中代表的电话号码是否有重复的,如果有重复的,那么输出其中重复次数>1的电话号码和其重复的次数;如果该字符串集中没有的重复的话,则输出“No duplicates.”。输入输出的样例,见题目给的样例即可。这里,针对字符串中字符和电话号码的具体映射规则如下:

(1)针对字符:

对字符串中的字符处理如下:

规则1:A,B,C 映射为 2

规则2:D,E,F 映射为 3

规则3:G,H,I  映射为 4

规则4:J,K,L  映射为 5

规则5:M,N,O映射为 6

规则6:P,R,S 映射为 7

规则7:T,U,V 映射为 8

规则8:W,X,Y映射为 9

(2)针对数字:

如果字符串中有数字的话,则该数字是多少,对应电话号码中的数字就是多少。

(3)其他注意:

给定的字符串只会出现数字0-9,(1)中的大写字母和连字符“-”,其他没有提到的字符不会出现。


个人解题思路参考:

这道题初看没什么难度,就是一个把字符串按照某种规则映射为数字,然后再根据其他要求进行处理,最后输出结果的过程。

然而,自己提交了几次,都是TLE。后来,分析了一下,主要有以下几个可能的原因:

(1)每个字符串集的字符串最高可达100,000;

(2)将字符串转换为电话号码的过程太慢,(起初是把数字和字母分开判断,然后再根据对应的规则映射为数字);其实这个过程可以改进,可以根据ASCII码建立对应的数组直接将字符串直接映射为电话号码中的数字,这个过程只需要判断一下给定的字符串的某个字符是否为连字符“-”即可;

(3)起初将转换得到的电话号码直接按“123-4567”的字符串形式存储,然后再进行判断是否有重复的(这一点很大程度上导致了TLE,算一下复杂度就知道了);其实这个过程也可以改进,可以将转化得到的电话号码按整数的形式存储,即把原先按字符串形式“123-4567”存储的电话号码存储为整数形式“1234567”,这样在判断是否有重复和按字典序升序输出结果会极大的降低所需时间;

(4)自己用qsort函数和sort函数分别试了一下,发现sort函数比qsort函数要快一点点,自己查了一下,大概是说,sort函数是qsort函数的升级版,对大数组采取9项取样,更完全的三路划分算法,具体的可以自己搜索一下或参考下方的链接。


以下是自己的解题代码,UVa_OJ上的运行时间为0.100,AC通过,仅供参考:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int tel[100010];
int mapLettertoDigit[]={0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,
						2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
int main(){
	#ifdef LOCAL
	freopen("755_input.txt","r",stdin);
	freopen("755_output.txt","w",stdout);
	#endif
	char s[100];
	int dataSetNum,telNum,i,j,k,isDup,count;
	scanf("%d",&dataSetNum);
	for(i=0;i<dataSetNum;i++){
		scanf("%d",&telNum);
		for(j=0;j<telNum;j++){
			tel[j]=0;
			scanf("%s",s);
			for(k=0;k<strlen(s);k++){
				if(s[k]!='-')
					tel[j]=tel[j]*10+mapLettertoDigit[s[k]-'0'];
			}

		}
		sort(tel,tel+telNum);
		isDup=0,count=1;
		for(j=1;j<telNum;j++){
			if(tel[j]==tel[j-1]){
				isDup=1;
				count++;
			}
			else{
				if(count>1){
					printf("%03d-%04d %d\n",tel[j-1]/10000,tel[j-1]%10000,count);
					count=1;
				}
			}
		}
		if(count>1)
			printf("%03d-%04d %d\n",tel[j-1]/10000,tel[j-1]%10000,count);
		if(!isDup)
			printf("No duplicates.\n");
		if(i<dataSetNum-1)
			printf("\n");		
	}
	return 0;
}

关于qsort函数和sort函数的详解和区别比较:

(1)点击打开链接

(2)点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值