【CSDN编程竞赛第六期】C++题解及个人感受

CSDN编程竞赛报名地址:https://edu.csdn.net/contest/detail/16

前言/背景

闲来无事逛CSDN的时候偶然发现了这一场第6期CSDN编程竞赛,本着周末也没什么事情,也很久没有做过题了的想法,报名了这一场比赛,打发一下周末时间。总体来说题目较为简单,适合初学者们学习和练手,也可以用来保持手感,题量适中,是一场很不错的入门级竞赛。

大赛简介

赛后大概看了一下,这个CSDN编程竞赛两周左右举办一次,举办方看上去就是CSDN官方,活动奖励也是很丰厚的。活动分为两个部分,竞赛和征文。竞赛部分只有4道编程题,满分100分,编程语言方面也是涵盖了Java、C、C++、C#、Python、JavaScript、lua、go等几乎全部主流编程语言,这一点还是比较人性化的,无论你习惯使用什么语言,这里都可以使用。征文部分需要参与话题文章创作,内容创作方向需围绕竞赛相关,如以往参加各类编程竞赛的比赛经历,本次竞赛的bug,对CSDN竞赛的建议等等。
注:所有参赛奖品需要同时参加考试和话题文章创作才可获得

参赛流程

参赛流程非常简单,入口在CSDN的学习界面有很明显的竞赛链接,点进去就是竞赛的介绍以及报名入口,简单的填写一些资料即可报名成功。报名之后会在考试前10分钟通过社区助手的私信提醒你竞赛即将开始,除此之外也会在开始前5分钟用短信的方式提醒你比赛即将开始。我当初就是报名之后就把这件事忘得死死的,看到短信才想起来我之前闲来无事报名了这场竞赛。

解题思路

我个人比较惯用的语言是C++,所以下面的代码也都是C++的代码,不过思路是通用的

1、题目名称:严查枪火
X国最近开始严管枪火。 像是“ak”,“m4a1”,“skr”。都是明令禁止的。 现在小Q查获了一批违禁物品其中部分是枪支。
小Q想知道自己需要按照私藏枪火来关押多少人。 (只有以上三种枪被视为违法)
测试用例:
4
aj
m4a1
skr
sc
运行结果: 2
思路很简单,只要遍历给定的字符串数组,只要当前字符串是三种违禁物品其中之一,就在最终结果数加一,也可以用map来记录每一个物品出现的次数,最后将你需要的加和返回。这里简单的用一个变量计数,遍历数组就好了,不用考虑太复杂。参考代码如下:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int solution(int n, std::vector<std::vector<std::string>>& vec){
	int result = 0;
	// TODO:
	for(auto str : vec)
	{
		for(auto ss : str)
		{
			if(ss == "ak"||ss == "m4a1"||ss=="skr")result++;
		}
	}
	return result;
}
int main() {
	int n;
	std::vector<std::vector<std::string>> vec;
	std::cin>>n;
	std::string line, token;
	for (int i = 0; i < n; i++){
		std::vector<std::string> s;
		getline(std::cin >> std::ws,line);
		std::stringstream tokens(line);
		while(std::getline(tokens, token, ' ')){
			s.push_back((token));
		}
		vec.push_back(s);
	}
	int result = solution(n,vec);
	std::cout<<result<<std::endl;
	return 0;
}

2、题目名称:鬼画符门
鬼画符门,每年都会统计自己宗门鬼画符消耗的数量,往年一直是大师兄管理, 但是这次鬼艺接手了, 你能帮鬼艺写一个
程序统计每年消耗数量最多的鬼画符吗?
测试用例: 5
red
red
red
blue
blue
运行结果: red
解题思路也很简单,定义一个map记录每一种符的数量,再定义一个string记录当前消耗数量最多的符,每一次符的数量增加时,和当前消耗数量最多的符进行一次比较,保持你记录的是当前消耗最多的,遍历结束后返回记录的字符串即可。参考代码如下:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
std::string solution(int n, std::vector<std::vector<std::string>>& vec){
	std::string result;
	// TODO:
	result = vec[0][0];
	std::map<std::string,int> mp;
	for(auto vec1 : vec)
	{
		for(auto str : vec1)
		{
			mp[str]++;
			if(mp[str] > mp[result])result = str;
		}
	}
	return result;
}
int main() {
	int n;
	std::vector<std::vector<std::string>> vec;
	std::cin>>n;
	std::string line, token;
	for (int i = 0; i < n; i++){
		std::vector<std::string> s;
		getline(std::cin >> std::ws,line);
		std::stringstream tokens(line);
		while(std::getline(tokens, token, ' ')){
			s.push_back((token));
		}
		vec.push_back(s);
	}
	std::string result = solution(n,vec);
	std::cout<<result<<std::endl;
	return 0;
}

3、题目名称:收件邮箱
已知字符串str,str表示邮箱的不标准格式。 其中”.”会被记录成”dot”,”@”记录成”at”。 写一个程序将str转化成可用
的邮箱格式。(可用格式中字符串中除了开头结尾所有”dot”,都会被转换,”at”只会被转化一次,开头结尾的不转化)
测试用例: xxxatqqdotcom
运行结果: xxx@qq.com
解题思路:利用std::string中提供的find和replace,实现指定字符串的替换,其中开头结尾的dot不转换,所以find的范围要从1开始,且如果find到的位置是倒数第三个,即find到的dot在末尾也是不需要替换的,at同理。由于所有的dot都要被替换所以要用一个循环,直到find到最后,而at只需要find一次。其它编程语言中也有类似的方法,能够快速的实现指定字符串的替换,C++的具体实现如下:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
std::string solution(std::string str){
	std::string result;
	// TODO:
	size_t start_pos = 1;
	while((start_pos = str.find("dot",start_pos)) != std::string::npos)
	{
		if(start_pos == str.length()-3)break;
		str.replace(start_pos,3,".");
		start_pos += 1;
	}
	start_pos = 1;
	start_pos = str.find("at",start_pos);
	if(start_pos != std::string::npos && start_pos != str.length() - 2)
	{
		str.replace(start_pos,2,"@");
	}
	result = str;
	return result;
}
int main() {
	std::string str;
	std::cin>>str;
	std::string result = solution(str);
	std::cout<<result<<std::endl;
	return 0;
}

4、题目名称:最长递增的区间长度
给一个无序数组,求最长递增的区间长度。如:[5,2,3,8,1,9] 最长区间 2,3,8 长度为 3
解题思路:通过两个变量实现,遍历整个数组,一个变量记录当前递增区间长度,另一个遍历记录最长递增区间长度,遍历结束后返回最长递增区间长度即可。参考代码如下:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int solution(int n, std::vector<int>& vec){
	int result = 1;
	// TODO:
	int temp = 1;
	for(int i = 1;i < n;++i)
	{
		if(vec[i] > vec[i-1])
		{
			temp++;
			result = temp > result ? temp : result;
		}
		else
		{
			temp = 1;
		}
	}
	return result;
}
int main() {
	int n;
	std::vector<int> vec;
	std::cin>>n;
	std::string line_0, token_0;
	getline(std::cin >> std::ws,line_0);
	std::stringstream tokens_0(line_0);
	while(std::getline(tokens_0, token_0, ' ')){
		vec.push_back(std::stoi(token_0));
	}
	int result = solution(n,vec);
	std::cout<<result<<std::endl;
	return 0;
}

经验心得

总体来说题量不多,难度不大,但C++给定的模板中输入部分编译不过可能会对一些初学者造成一些困扰,建议调整为给定接口函数,参赛者只负责函数内的代码编写。当然规则介绍中也说了可按个人代码习惯修改,不过个人认为这是一件很没有必要的事情。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值