学习C++从娃娃抓起!记录下CCF-GESP备考学习过程中的题目,记录每一个瞬间。
附上汇总贴:GESP编程能力等级认证C++编程真题解析 | 汇总
单选题
第1题
下列关于排序的说法,正确的是( )。
A. 冒泡排序是最快的排序算法之一。
B. 快速排序通常是不稳定的。
C. 最差情况,N 个元素做归并排序的时间复杂度为 O(N)。
D. 以上均不正确。
【答案】:B
【解析】
A选项冒泡的时间复杂度是 O ( n 2 ) O(n^2) O(n2),C选项归并排序时间复杂度是固定的O(nlogn)
第2题
下面的程序属于哪种算法( )。
int pos[8];
void queen(int n) {
for (int i = 0; i < 8; i++) {
pos[n] = i;
bool attacked = false;
for (int j = 0; j < n; j++)
if (pos[n] == pos[j] || pos[n] + n == pos[j] + j || pos[n] - n == pos[j] - j) {
attacked = true;
break;
}
if (attacked)
continue;
if (n == 7) {
return;
} else {
queen(n + 1);
}
}
}
A. 贪心算法
B. 动态规划
C. 深度优先搜索
D. 广度优先搜索
【答案】:C
【解析】
第16行自己调用自己,所以是DFS
第3题
下面有关C++类的说法,错误的是( )。
A. C++类对象销毁时,会执行析构函数。
B. C++类可以通过定义构造函数实现自动类型转换。
C. C++类可以通过重载 [ ] 运算符实现通过给定下标访问数组成员的元素。
D. C++类可以包含任意类型的成员变量。
【答案】:D
【解析】
类不能包含自身,也不能使用定义在它下方的其他类
第4题
一个连通的简单无向图,共有28条边,则该图至少有( )个顶点。
A. 6
B. 7
C. 8
D. 9
【答案】:C
【解析】
找到最小的n,使得 C n 2 ≥ 28 C_{n}^{2}\ge 28 Cn2≥28,n为8
第5题
以下哪个方案不能合理解决或缓解哈希表冲突( )。
A. 在每个哈希表项处,使用单链表管理该表项的冲突元素。
B. 建立额外的单链表,用来管理所有发生冲突的元素。
C. 使用不同的哈希函数再建立一个哈希表,用来管理所有发生冲突的元素。
D. 用新元素覆盖发生冲突的哈希表项。
【答案】:D
【解析】
新元素覆盖之前的元素,肯定不行
第6题
已知一颗二叉树的中序遍历序列为:{C F B A E D G},后序遍历序列为:{F C B E G D A},则下列说法中正确的是( )。
A. 该树是平衡二叉树。
B. 该树的高为4。
C. 该树有4个叶节点。
D. 以上说法都不对。
【答案】:B
【解析】
画出二叉树,A选项平衡二叉树是指左儿子深度和右儿子深度最多只差1,B的左儿子深度为2,没有右儿子,所以错误。树的高度是4,3个叶子节点
第7题
以下关于二叉排序树的说法,正确的是( )。
A. 二叉排序树的中序遍历序列一定是有序的。
B. 在含 n 个节点的二叉排序树中查找元素,最差情况的时间复杂度为 。
C. 二叉排序树一定是二叉平衡树。
D. 以上说法都不对。
【答案】:
【解析】
二叉排序树是指左子树的所有节点的权值小于根,右子树的所有节点的权值大于根。
B选项最差的时间复杂度是O(n),C选项二叉排序树不一定是二叉平衡树,如只有右节点的二叉排序树(一条链)
第8题
已知 x 为 double 类型的变量,且值大于0,则下列表达式的值一定大于0的是( )。
A. sin(x) / x
B. exp(x) - x
C. log(x) - x
D. x * x - x
【答案】:B
【解析】
A选项, π < x < 2 π \pi \lt x \lt 2\pi π<x<2π时sin(x)<0。B选项 e x e^x ex,当x越来越大, e x e^x ex也越来越大,x为0是 e x − x = 1 e^x-x=1 ex−x=1,所以正确。C选项,设x=e,log(e) - e = 1 - e <0(e约为2.72)。D选项,设x=0.5,该选项显然错误
第9题
一个简单有向图有10个结点、30条边。再增加多少条边可以成为完全图。( )
A. 60
B. 70
C. 15
D. 20
【答案】:A
【解析】
10个节点的简单有向图,如果是完全图,那么边数是n * (n-1) = 10 * 9 = 90条边,90 - 30 = 60。
第10题
下列选项中,哪个可能是下图的深度优先遍历序列( )。
A. 8, 6, 1, 5, 3, 4, 2, 10, 7, 12, 11, 9
B. 7, 8, 6, 4, 2, 1, 5, 3, 12, 9, 11, 10。
C. 8, 10, 12, 9, 11, 4, 5, 3, 2, 1, 6, 7
D. 7, 8, 10, 9, 11, 12, 4, 5, 1, 2, 3, 6。
【答案】:C
【解析】
A选项,10下一个可以走到12。B选项需要先遍历10,才能遍历到12。D选项10下一个不能走到9
第11题
下面 schedule 函数的时间复杂度为( )。
#include <algorithm>
using namespace std;
struct activity {
int id, start, end;
};
bool compare(activity a, activity b) {
return a.end < b.end;
}
int schedule(int n, activity * p) {
sort(p, p + n, compare);
int cnt = 0, end = 0;
for (int i = 0; i < n; i++) {
if (p[i].start >= end) {
end = p[i].end;
cnt++;
}
}
return cnt;
}
A.O(n)
B.O(log(n))
C.O(nlog(n))
D. O ( n 2 ) O(n^2) O(n2)
【答案】:C
【解析】
sort排序的时间复杂度是O(nlog(n)),for循环的时间复杂度是O(n),加起来选择最大值,则为O(nlog(n))
第12题
下面 search 函数的平均时间复杂度为( )。
int search(int n, int * p, int target) {
int low = 0, high = n;
while (low <= high) {
int middle = (low + high) / 2;
if (target == p[middle]) {
return middle;
} else if (target > p[middle]) {
low = middle + 1;
} else {
high = middle - 1;
}
}
return -1;
}
A.O(n)
B.O(log(n))
C.O(1)
D.可能无法返回
【答案】:B
【解析】
代码为二分查找答案,时间复杂度是O(log(n))
第13题
下面 count_triple 函数的时间复杂度为( )。
int count_triple(int n) {
int cnt = 0;
for (int a = 1; a <= n; a++)
for (int b = a; a + b <= n; b++)
for (int c = b; a + b + c <= n; c++)
if (a * a + b * b == c * c)
cnt++;
return cnt;
}
A.O(N)
B. O ( N 2 ) O(N^2) O(N2)
C. O ( N 3 ) O(N^3) O(N3)
D. O ( N 4 ) O(N^4) O(N4)
【答案】:C
【解析】
三层for循环,结束都是到n,时间复杂度就是 O ( n 3 ) O(n^3) O(n3),for中的变量及条件,只是修改了 n 3 n^3 n3前的系数而已
第14题
下面程序的输出为( )。
#include <iostream>
using namespace std;
int down(int n) {
if (n <= 1)
return n;
return down(n - 1) + down(n - 2) + down(n - 3);
}
int main() {
cout << down(6) << endl;
return 0;
}
A. 6
B. 13
C. 20
D. 无法正常结束。
【答案】:
【解析】
将递归转为递推后计算,计算结果为6
-1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
-1 | 0 | 1 | 0 | 1 | 2 | 3 | 6 |
第15题
下面的程序使用邻接矩阵表达的带权无向图,则从顶点0到顶点3的最短距离为( )。
int weight[4][4] = {
{0, 2, 5, 8},
{2, 0, 1, 7},
{5, 1, 0, 4},
{8, 7, 4, 0}};
A. 6
B. 7
C. 8
D. 9
【答案】:B
【解析】
0到1是2,1到2是1,2到3是4,总共2+1+4=7
判断题
第16题
祖冲之是南北朝时期杰出的数学家、天文学家,其主要贡献在数学、天文历法和机械制造三方面。他首次将“圆周率”精算到小数第七位,即在3.1415926和3.1415927之间。
A.正确
B.错误
【答案】:A
【解析】
基本常识
第17题
C++语言中,表达式 2 ^ 3 的结果类型为 int 、值为 8 。( )
A.正确
B.错误
【答案】:B
【解析】
2和3进行异或,不是 2 3 2^3 23,是1
第18题
一棵有 N 个节点的完全二叉树,则树的深度为 ⌊ l o g 2 ( N ) ⌋ + 1 \lfloor log_2(N)\rfloor + 1 ⌊log2(N)⌋+1。( )
A.正确
B.错误
【答案】:A
【解析】
设n=7和8,15和16,代入计算后发现公式是正确的
第19题
能用动态规划解决的问题,一般也可以用贪心法解决,但动态规划的效率更高。( )
A.正确
B.错误
【答案】:B
【解析】
两个是不一样的算法,动态规划要求最优子结构
第20题
使用 math.h 或 cmath 头文件中的正弦函数,表达式 sin(30) 的结果类型为 double 、值约为 0.5 。( )
A.正确
B.错误
【答案】:B
【解析】
sin中的数应该是弧度,而不是角度
第21题
要求出简单有向图中从顶点 A 到顶点 B 的最短路径,在深度优先搜索和广度优先搜索中选择,广度优先更适 合。( )
A.正确
B.错误
【答案】:A
【解析】
使用广搜,搜到点的路径就是最短路径
第22题
某 N 个表项的哈希表,在发生哈希函数冲突时采用向后寻找空位的方法解决冲突。其查找操作的平均时间复杂度为 O(1),即使当该哈希表的每个表项都有元素时,查找操作的平均时间复杂度仍为 O(1)。( )
A.正确
B.错误
【答案】:B
【解析】
向后查找,时间复杂度肯定不是O(1),
第23题
动态规划有递推实现和递归实现,有时两种实现的时间复杂度不同。( )
A.正确
B.错误
【答案】:A
【解析】
递归和递推的时间复杂度不一样
第24题
围棋游戏中,判断落下一枚棋子后是否会提掉对方的子,可以使用泛洪算法来实现。( )
A.正确
B.错误
【答案】:A
【解析】
白字旁边的黑子,使用泛洪算法遍历这个黑字周围的黑字(个人不会下围棋)
第25题
类 B 继承了抽象类 A ,但未实现类 A 中的纯虚函数 f ,则类 B 不能直接实例化。( )
A.正确
B.错误
【答案】:A
【解析】
如果A中声明了纯虚函数(一类特殊的虚函数),但不定义。派生出来的B类要实现这个纯虚函数,否则类B无法实例化,不然根本不知道怎么调用函数f
编程题
第26题 交流问题
【题目描述】
来自 2 所学校 A 校、B 校的 名同学相聚在一起相互交流,方便起见,我们把这些同学从 1 至 N 编号。他们共进行了 M 次交流,第 i 次交流中,编号为 u i , v i u_i,v_i ui,vi 的同学相互探讨了他们感兴趣的话题,并结交成为了新的朋友。
由于这次交流会的目的是促进两校友谊,因此只有不同学校的同学之间会交流,同校同学并不会相互交流。
作为 A 校顾问,你对 B 校的规模非常感兴趣,你希望求出 B 校至少有几名同学、至多有几名同学。
【输入】
第一行两个正整数 N,M,表示同学的人数,交流的次数。
接下来 M 行,每行两个正整数 u i , v i u_i,v_i ui,vi,表示一次交流。
题目保证输入合法,即交流一定是跨校开展的。
【输出】
输出一行两个整数,用单个空格隔开,分别表示 B 校至少有几名同学、至多有几名同学。
【输入样例】
4 3
1 2
2 3
4 2
【输出样例】
1 3
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int n, m, s, t, ans1, ans2, num[3], col[N];
vector<int> e[N];
void dfs(int u)
{
for (auto v : e[u]) { // 遍历u号点相邻的所有v
if (col[v] == 0) { // 如果v也没有被染色
col[v] = 3 - col[u]; // 假设col[u]是1,则col[v]是2;假设col[u]是2,则col[v]是1
num[col[v]]++;
dfs(v);
}
}
}
int main()
{
cin >> n >> m;
for (int i=1; i<=m; i++) {
cin >> s >> t;
e[s].push_back(t);
e[t].push_back(s);
}
for (int i=1; i<=n; i++) {
if (col[i]==0) { // 如果这个点还没有被染色,例如找到一个新的连通块
num[1] = 1; num[2] = 0;
col[i] = 1;
dfs(i); // 从i号点出发进行遍历
ans1 += min(num[1], num[2]);
ans2 += max(num[1], num[2]);
}
}
cout << ans1 << " " << ans2 << endl;
return 0;
}
【运行结果】
4 3
1 2
2 3
4 2
1 3
第27题 俄罗斯方块
【题目描述】
小杨同学用不同种类的俄罗斯方块填满了一个大小为 n × m n\times m n×m 的网格图。
网格图由 n × m n\times m n×m 个带颜色方块构成。小杨同学现在将这个网格图交给了你,请你计算出网格图中俄罗斯方块的种类数。
如果两个同色方块是四连通(即上下左右四个相邻的位置)的,则称两个同色方块直接连通;若两个同色方块同时与另一个同色方块直接或间接连通,则称两个同色方块间接连通。一个俄罗斯方块由一个方块和所有与其直接或间接连通的同色方块组成。定义两个俄罗斯方块的种类相同当且仅当通过平移其中一个俄罗斯方块可以和另一个俄罗斯方块重合;如果两个俄罗斯方块颜色不同,仍然视为同一种俄罗斯方块。
例如,在如下情况中,方块 1 和方块 2 是同一种俄罗斯方块,而方块 1 和方块 3 不是同一种俄罗斯方块。
方块1: 方块2: 方块3:
1 1 1 2 2 2 1
1 1 2 2 1 1
1 1
【输入】
第一行包含两个正整数 n,m,表示网格图的大小。
对于之后 n 行,第 i 行包含 m 个正整数 a i 1 , a i 2 , … , a i m a_{i1},a_{i2},\dots,a_{im} ai1,ai2,…,aim,表示该行 m 个方块的颜色。
【输出】
输出一个非负整数,表示俄罗斯方块的种类数。
【输入样例】
5 6
1 2 3 4 4 5
1 2 3 3 4 5
1 2 2 3 4 5
1 6 6 7 7 8
6 6 7 7 8 8
【输出样例】
7
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 505;
int n, m, k, s, t, sx, sy, a[N][N], ans, vis[N][N];
int d[4][2] = {0,1,1,0,0,-1,-1,0};
vector<pair<int, int>> e;
set<vector<pair<int, int>>> se;
void dfs(int x, int y)
{
e.push_back({x-sx, y-sy}); // 将每个节点的相对位置放到e向量中
vis[x][y] = 1; // 并标记访问过
for (int i=0; i<4; i++) { // 上下左右遍历
int xx = x + d[i][0], yy = y + d[i][1];
if (xx>=1 && xx<=n && yy>=1 && yy<=m && a[xx][yy]==a[x][y] && !vis[xx][yy]) { // 符合条件的格子继续遍历,最终会找到一个连通块
dfs(xx, yy);
}
}
}
int main()
{
cin >> n >> m;
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
cin >> a[i][j];
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
if (!vis[i][j]) {
sx = i, sy = j; // 相对位置
dfs(i, j);
se.insert(e); // 将e向量放到se的集合中,正好可以达到去重的目的
e.clear();
}
cout << se.size();
return 0;
}
【运行结果】
5 6
1 2 3 4 4 5
1 2 3 3 4 5
1 2 2 3 4 5
1 6 6 7 7 8
6 6 7 7 8 8
7