第一题 元音字母(vowel)
【题意分析】
给定一个长度小于等于106且只包含字母的字符串,求元音字母(a,e,i,o,u)的个数。
【解题思路】
对于每一位字符逐一进行判断并统计,但要注意大小写字母的区别。可以统一转换为大写或小写方便判断。
【时空复杂度】
时间复杂度:O(n)
空间复杂度:O(n)
【解题反思】
此题作为比赛的第一题,难度较低,但仍要注意一些细节:
1. 若C++选手使用字符数组,考虑到数据范围较大,必须设为全局变量,否则可能引发运行时错误。
2. C++中的string是从第0位开始储存的,如果从1开始计算可能导致答案错误。
3. 题目中已经明文提示了,要注意大小写的区别。
【参考程序】
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
const int maxlen = 1e6 + 100;
char str[maxlen];
int main(void) {
freopen("vowel.in","r", stdin);
freopen("vowel.out","w", stdout);
gets(str);
int ans =0;
for (int i= 0; str[i] != '\0'; i++) { //char数组的最后一位为'\0'
char ch= tolower(str[i]); //统一将当前位转为小写
ans +=ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u';
}
printf("%d\n",ans);
return 0;
}
第二题 直角坐标系(coordinates)
【题意分析】
给定平面直角坐标系中的n个格点(所有的点两两不同),按一定的原则绘制该坐标系:
1. 整个坐标系分为四个象限,只要该象限或与其相邻的两个象限中同时存在格点,就必须将该象限绘制出来。
2. 格点所在的坐标表示为‘*’
3. 在与原则2不冲突的情况下,x 轴表示为‘|’,y轴表示为‘-’,原点表示为‘+’
【解题思路】
直接按照题意模拟即可,但具体的实现上要注意细节。平面直角坐标系中点坐标的表示法为(x,y),但输出时是由上至下(y递减)、由左至右(x递增)的,故要进行处理。
首先要确定输出的范围,通过观察样例可以发现,如果记最终输出的坐标系当中x的取值范围为[minx,maxx],那么就有minx=min{ xi,0},maxx=max{ xi,0},y同理。
之后则以y递减,x递增的顺序打印整个坐标系,判断当前位置是否存在点有两种方法:
一、数组计数法(我在考试时的写法)
考虑到数据范围较小,且不存在重复的点,不妨在输入时用bool数组a[j][i]表示横坐标为j、纵坐标为i的位置是否存在点。但C++中数组下标从0开始,又因为坐标的绝对值不超过100,因此可以统一加上100即可避免出现负数的问题。此方法的编程复杂度较低。
30%的做法:不考虑点坐标的正负性,直接进行标记。
二、 点排序法
可以将输入的点用struct保存(也可用STL中的pair实现)并按输出顺序的优先级排序,在输出时用k表示下一个格点在struct数组中的下标,若p[k].x==j且p[k].y==i则当前位置是格点,输出‘*’后将k累加,指向下一个点。此方法的空间复杂度较低。
需要注意的是,由于枚举每一个位置并判断输出的这一过程是不可能省去的,故时间复杂度不可能比方法一更优。但此方法不必担心坐标的正负性问题,风险较低。
【时空复杂度】
不妨记坐标值的跨度范围为m,点的个数为n(显然0≤n≤m2),有:
数组计数法:
时间复杂度:O(m2)
空间复杂度:O(m2)
点排序法:
时间复杂度:O(m2)
空间复杂度:O(n)
【解题反思】
1. 我在考试时编写的程序没有AC,是因为忽略了在原点位置有一个点的情况。由此可见,对于此类难度不高的模拟题,一定要小心谨慎,“细节决定成败”。
2. 在考试这种限时的场合,在考虑到多种不同的实现方法时,应粗略计算各自的时空复杂度、编程复杂度和期望得分,加以比较后再决定策略,编写程序。
【参考程序】
方法一:
#include<algorithm>
#include<cctype>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
usingnamespace std;
constint maxp = 1e3; //坐标值的最大跨度,稍微开大一些,空间上不会有问题
intn;
boolf[maxp][maxp]; //第一维为横坐标(列),第二维为纵坐标(行)!!
intmain(void) {
freopen("coordinates.in","r", stdin);
freopen("coordinates.out","w", stdout);
scanf("%d", &n);
memset(f, false, sizeof f);
int minx = 0, miny = 0, maxx = 0, maxy = 0;//必须包含坐标轴,故初始化为0
for (int i = 0; i < n; i++) {
intx, y;
scanf("%d%d", &x, &y);
minx =