PTA写BUG日志——哈希篇(算法笔记上机实战)

2021年7月16日

哈希第一弹

题目传送门–B1033旧键盘打字
没错没错,这是2/5通过率版本,第一版3/5,改了之后不仅还是超时,结果正确率又降了,嘤嘤嘤~~

//1033
#include<bits/stdc++.h>
using namespace std;
char test[200000];
char bad[100];
bool flag=false;
map<char,int>mp;
int main(){
	scanf("%s%s",bad,test);
	for(int i=0;i<strlen(bad);i++){
		if(bad[i]=='-'||bad[i]=='+'||bad[i]=='.'||bad[i]==','){
			flag=true;//大写失灵 
		
		}
		mp[bad[i]]=true;
		if(bad[i]<='Z'&&bad[i]>='A'){
			mp[bad[i]-'A'+'a']=true;
		}
	}
	int count=0;
	for(int i=0;i<strlen(test);i++){
		if(test[i]<='Z'&&test[i]>='A'&&flag)continue;
		if(mp[test[i]])continue;
		count++;
		printf("%c",test[i]);
	}
	printf("\n");
	return 0;
}

然后,如果是熟悉了string类的自带的一些很”妙“的操作就真的很妙了!
参考了柳神的代码

#include<iostream>
#include<cctype>
using namespace std;
int main(){
	string bad,test;
	getline(cin,bad);
	getline(cin,test);
	for(int i=0;i<test.length();i++){
		if(bad.find(toupper(test[i]))!=string::npos)continue;//是一定打不出来的
		if(isupper(test[i])&&bad.find('+')!=string::npos )continue;//错误原因,题意的理解,只有+代表上档键
		cout<<test[i];
	}
	cout<<"\n";
	return 0;
}

终于跑通了,之前主要是题意理解错了,上档只有+,然后输入的测试中+自己本身也算一个字符;超时的原因大概是自己造的‘轮子’效率没有string自带的函数高;
**string::npos
isupper(str)😗*判断是否为大写
**toupper(str):**改写成大写

哈希第二弹

题目传送门–甲级1092到底买不买
这一题涉及到的是哈希,emm讲真我没看出来
不过因为C++很多函数库不熟,所以自己就着上一题柳神的思路查了一下string 的一些奇奇怪怪基础用法
一次通过太感动啦

//1092甲级
#include<iostream>
#include<cctype>
using namespace std;
//如果符合,则需要输出额外需要买的
//如果不符合,需要输出还缺的个数
string shop;
string want;
int main(){
	getline(cin,shop);
	getline(cin,want);
	int num=want.length();//需要的
	int sum=num;
	for(int i=0;i<shop.length();i++){
		if(want.find(shop[i])!=string::npos){
			num--;
			want.erase(want.begin()+want.find(shop[i]));
		}
	} 
	if(num<=0){
		cout<<"Yes "<<shop.length()-sum<<endl;
	}else{
		cout<<"No "<<num<<endl;
	}
	return 0;
} 

**string.erase()**删除指定位置的字符
**string.find()**查找特定字符,返回他在string中的位置
它有具体几种用法Str的find与erase函数

哈希第三弹

一开始以为是输出所有最大值字母来着,排序题最近可能练的多了一点嘿嘿~
这题很基础,不过又掌握了**tolower()**的用法,算是对string类型进一步熟悉熟悉😀

//1042字符统计
#include<bits/stdc++.h>
using namespace std;
string a;
//统计英文字母,频率 
struct node{
	char ch='?';
	int time=0;
}num[26];
bool cmp(node a,node b){
	if(a.time!=b.time)return a.time>b.time;
	else return a.ch<b.ch;
}
int main(){
	getline(cin,a);
	for(int i=0;i<a.length();i++){
		if(a[i]<='z'&&a[i]>='a'){
			num[a[i]-'a'].time++;
			num[a[i]-'a'].ch=tolower(a[i]);
		}else if(a[i]<='Z'&&a[i]>='A'){
			num[a[i]-'A'].time++;
			num[a[i]-'A'].ch=tolower(a[i]);//大写转小写 
		}
	}
	sort(num,num+26,cmp);
	int maxn=num[0].time;
	for(int i=0;i<26;i++){
		if(num[i].time==maxn){
			if(i==0)
			printf("%c %d",num[i].ch,num[i].time);
			else 
			printf(" %c %d",num[i].ch,num[i].time);
			break;
		}
	}
	printf("\n");
	return 0;
} 

哈希第三弹

1043乙组输出PATest
这题好像没有什么坑🕳,方法也比较多,当然我的方法用了map映射,其实因为只有6个字母,其实也没有必要,代码显得相当冗余臃肿啦

//1043
#include<bits/stdc++.h>
using namespace std;
//打印PATest
string a; 
string c="PATest";
map<char,int>mp;
int main(){
	getline(cin,a);
	mp['P']=0;mp['A']=0;mp['T']=0;
	mp['e']=0;mp['s']=0;mp['t']=0;
	int sum=0;
	for(int i=0;i<a.length();i++){
		if(a[i]=='P'||a[i]=='A'||a[i]=='T'||a[i]=='e'||a[i]=='s'||a[i]=='t'){
			mp[a[i]]++;
			sum++;
		}
	}
	while(sum){
		for(int i=0;i<6;i++){
			if(mp[c[i]]){
				mp[c[i]]--;
				printf("%c",c[i]);
				sum--;
			}
			if(sum==0)break;
		}
	}
	return 0;
} 

哈希第四弹

B1047团体编程赛
这是一个虽然AC 但是很明显有很大漏洞的代码——单纯的使用了线性映射,在数据集小的测试样例上OK但是可以预见,测试数据稍微残酷一点,这份代码的表现会很糟糕QAQ
不过搜了一下……好像也没有看到压缩空间的解法……呜呜呜

//1047
#include<bits/stdc++.h>
using namespace std;
struct node{
	int team;
	int id;
	int score;
};
struct Team{
	int id;
	int score=0;
};
int n;
Team b[20000];
bool cmp(Team a,Team b){
	return a.score>b.score;
}
int main(){
	scanf("%d",&n);
	int team,id,score;
	for(int i=0;i<n;i++){
		scanf("%d-%d %d",&team,&id,&score);
		
		b[team].id=team;
		b[team].score+=score;
	}
	sort(b,b+10000,cmp);
	printf("%d %d",b[0].id,b[0].score);
	return 0;
} 

哈希第五弹

A1041 Be Unique
这题不难,关键就是……开数组开小了,10000和100000的区别,下次要细心一点呀
关键是,报错的时候说“答案错误”,应该是“段错误”昂

//甲级1041:哈希
#include<bits/stdc++.h>
using namespace std;
int n;
int num[101100];
int ccount[101100];
int main() {
	scanf("%d",&n);
	memset(ccount,0,sizeof(ccount)); 
	for(int i=0;i<n;i++){
		scanf("%d",&num[i]);//选择的数据 
		ccount[num[i]]++;
	}
	
	for(int i=0;i<n;i++){
		//debug
		//printf("数字为:%d 次数为: %d\n",num[i],ccount[num[i]]); 
		if(ccount[num[i]]==1){
			
			printf("%d",num[i]);
			return 0;
		}
	}
	printf("None");
	return 0;
}

哈希第六弹

A1050 String Subtraction
这题也是,没有什么难度,规定了时间的话,肯定不能两个字符串轮流遍历啦,考虑用哈希~~(其实是因为俺在集中练习哈希,感觉可能没有这个背景的话,我也是暴力超时的那个嘿嘿)~~
ac如下:
果然按着算法笔记的顺序来练习就不会轻易被劝退啦

//1050
#include<bits/stdc++.h>
using namespace std;
//快速输出两个字符串相减的结果 
map<char,int>mp;
string a,b; 
int main(){
	getline(cin,a);
	getline(cin,b);
	for(int i=0;i<b.length();i++ ){
		if(!mp[b[i]]){
			mp[b[i]]=1;
		}else{
			mp[b[i]]++;
		}
	}
	for(int i=0;i<a.length();i++){
		if(!mp[a[i]]){
			printf("%c",a[i]);
			continue;
		}
	}
	
	return 0;
}

哈希第七弹

没想到这么快就快结束哈希啦(排序那边还欠了一点收尾呜呜呜~~~)
B1005继续(3n+1)猜想
基础题,但是没想到PTA的数据也有问题,题目中明明给的限制是不超过100,实际得100000才没有“段错误”的报错,嗨呀,万望仔细

//1005
#include<bits/stdc++.h>
using namespace std;
/*
对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;
如果它是奇数,那么把 (3n+1) 砍掉一半。
这样一直反复砍下去,最后一定在某一步得到 n=1。
*/
int n;
int num[10900];
int mp[50000]={0};//某一个数字,是否可以由其他数字得到
void f(int n){
	if(mp[n]){
		//第一个数字已经被标记过了
		 mp[n]++;
		 return;
	}else{
		mp[n]=1;
	}
	while(n!=1){
	//	printf("%d\n",n);
		if(n%2==0){
			n/=2;
		}else{
			n=(3*n+1)/2;
		}
		if(!mp[n]){
			mp[n]=1;//第一个数字 
		}else{
			mp[n]++;
		}
	}
	return ;
} 
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&num[i]);
	}
	for(int i=0;i<n;i++){
		f(num[i]);
	}
	bool flag=false;
	//printf("chulai"); 
	sort(num,num+n);
	for(int i=n-1;i>=0;i--){
		if(mp[num[i]]&&mp[num[i]]==1){
			if(!flag)
			printf("%d",num[i]);
			else
			printf(" %d",num[i]);
			flag=true;
		}
	}
	return 0;
}

哈希第八弹

A1048 Find Coins
其实完全没有感觉到是甲级的题目危险发言
也没有感觉到是散列的题目,感觉不是很难✌

//1048甲级
#include<bits/stdc++.h>
using namespace std;
int coin[200000];
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		scanf("%d",&coin[i]);
	}
	sort(coin,coin+n);
	int amin,amax;
	int i=0;
	amin=coin[i];
	amax=coin[--n];
	while(i<n){
		if(amin+amax==m){
			printf("%d %d",amin,amax);
			return 0;
		}else if(amin+amax>m){
			amax=coin[--n];
		}else{
			amin=coin[++i];
		}
	}
	printf("No Solution");
	return 0;
} 

就酱,哈希就暂告一段落叭~~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值