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++给定的模板中输入部分编译不过可能会对一些初学者造成一些困扰,建议调整为给定接口函数,参赛者只负责函数内的代码编写。当然规则介绍中也说了可按个人代码习惯修改,不过个人认为这是一件很没有必要的事情。