PTA B1029. 旧键盘 (20)

1029 旧键盘 (20 分)
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及实际被输入的文字,请你列出肯定坏掉的那些键。

输入格式:
输入在 2 行中分别给出应该输入的文字、以及实际被输入的文字。每段文字是不超过 80 个字符的串,由字母 A-Z(包括大、小写)、数字 0-9、以及下划线 _(代表空格)组成。题目保证 2 个字符串均非空。

输出格式:
按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有 1 个坏键。

输入样例:
7_This_is_a_test
_hs_s_a_es
输出样例:
7TI

思路1:

Encrypt函数用来除去key字符串中重复的字符,并存入keych中,main函数中count记录要存入str3数组元素的个数,while循环采用双指针遍历两个字符串,若两指针指向的元素不同,则将str1指针指向的元素的大写存入str3数组中,否则指针同时后移。while循环结束后,str1字符串必定还未遍历完,应该继续处理,将剩余元素改成大写存入str3中,最后调用Encrypt函数进行去重存放在str4中,最后输出str4即可。

参考代码1:

#include <iostream>
#include <cstring>
using namespace std;
void Encrypt(char* keych,char *key){//除去key字符串重复的字符,并存入keych中; 
    keych[0]=key[0];//初始化首字符; 
    int j=0,flag;//j代表keych数组即将存放的下标;
    for(int i=0;i<strlen(key);i++){//遍历key数组; 
        flag=1;
        //判断key[i]是否与keych中的某个字符相等,如果有相等的字符,则将flag置为0; 
        for(int k=0;k<j+1;k++){//遍历keych数组中以存储的每一个元素;
            if(key[i]==keych[k])
                flag=0;
        }
        if(flag){//若flag=1,则说明keych[0-j]中不存在与key[i]相同的字符,那就将这个元素存放在keych数组的j+1位置。
            j=j+1;
            keych[j]=key[i];
        }
    }
    keych[j+1]='\0';//处理结尾;
}

int main(){
	string str1,str2;//str1应该被输入的字符串,str2实际被输入的字符串; 
	cin>>str1>>str2;
	int i,j=0;
	char str3[100],str4[100]; 
	int count=0;
	while(str1[i]!=NULL&&str2[j]!=NULL){//双指针遍历; 
		if(str1[i]!=str2[j]){//若两指针指向的字符不同则输出第一个字符串指针对应字符; 
			if(islower(str1[i])){//若是小写改成大写存入待去重数组str3; 		
				str3[count]=toupper(str1[i]);//
			}
			else {	
				str3[count]=str1[i]; 
			}    
			i++;
			count++;
		} 
		else {//若相同则指针同时后移; 
			i++;
			j++;
		}
	}
	
	if(str2[j]==NULL){//处理str1剩余部分,(很有可能这些字符,str2都没有); 
		for (int k=i;k<str1.length();k++) {
			if(islower(str1[k])){//若是小写改成大写存入待去重数组str3; 		
				str3[count]=toupper(str1[k]);//
			}
			else {	
				str3[count]=str1[k]; 
			} 
			count++; 
		}
	} 
	Encrypt(str4,str3);
	cout<<str4;
	return 0;
}

思路2:

用HashTable来标记某一字符是否被输出,外层for循环遍历str1的每一个元素,内层for循环遍历str2的每一个元素并用c1,c2临时存放当前遍历元素,若是小写则改写为大写。在遍历中若c1与c2相同即c1在第二个字符串中出现过,则结束内层循环。若内层循环正常结束,且c1还未被输出过,则输出c1,再将HashTable[c1]置为true表示已输出。程序继续执行,知道外层循环也结束,则输出完毕。

参考代码2:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; 
int main(){
	string str1,str2;
	bool HashTable[128]={false};//HashTable数组用来标记字符是否已被输出;
	cin>>str1>>str2;
	int len1=str1.length(),len2=str2.length();
	for(int i=0;i<len1;i++){
		int j;
		char c1,c2;
		for(j=0;j<len2;j++){
			c1=str1[i];
			c2=str2[j];
			if(c1>='a'&c1<='z') c1-=32;//若是小写字母,则转换为大写; 
			if(c2>='a'&c2<='z') c2-=32;
			if(c1==c2) break;//若c1在第二个字符串中出现,则跳出。 
		}
		if(j==len2&&HashTable[c1]==false){
			printf("%c",c1);//在第二个字符串中未出现c1,且c1未输出过;
			HashTable[c1]=true; 
		} 
	}
	return 0;
}

点评:

①此题属于散列型,在要求不重复输出数据时经常使用,采用bool型数组HashTable可以实现空间换时间的时间复杂度简化。
②思路1是野路子,Encrypt函数可以去除字符串中重复的字符,可达到题目的输出要求。而思路2则是此类问题的标准解法,需要充分理解并熟练掌握。
③参考代码1中涉及到许多函数例如isupper(),toupper(),tolower.(),用以解决大小写转换问题,也可采用参考代码2中的c2-=32,需对ASCII码有一定的了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值