C++中学组
2026-09-12 21:57:10
发布于:广东
- 循环与函数基础
1)循环执行次数:while 和 do-while 的核心区别是:do-while 至少执行一次,两者执行次数不一定相同。
2)函数参数传递:值传递参数在函数内修改,不会影响实参;若要修改需用引用(&)或指针。
3)函数声明与定义:自定义函数可以写在主函数后面,但必须在主函数之前进行函数声明。
💡 复习建议:深刻理解函数栈帧、值传递与引用传递的底层区别。 - 字符串处理
1)strcmp 函数:返回 0 代表两个字符串完全相等;返回负数代表前者小,正数代表前者大。
2)strlen 函数:strlen("abcd") 的值是 4(不包含 \0)。
3)string 类:find 找不到子串时返回 string::npos(通常是一个极大值),不是 0。
4)string 拼接:string 类型可以直接用 + 拼接字符串。
💡 复习建议:熟练区分 C 风格字符串函数(strlen, strcmp, strcpy)与 C++ string 类的方法。 - 算法与数据结构
1)二分查找:时间复杂度为 O(log n),每次可以排除一半的区间。
2)排序算法稳定性:冒泡排序是稳定的;选择排序是不稳定的。
3)结构体比较:两个同类型的结构体变量不能直接用 == 比较是否相等(需手动写成员逐个比较)。
💡 复习建议:掌握各类排序算法的时空复杂度及稳定性,理解结构体在内存中的对齐与比较逻辑。 - 编程题专项
1)二维图案输出(花园种植):考察二维数组的边界(上下左右)、两条对角线(ij 和 i+jn-1)的条件判断。
2)二分查找应用题(找最后一个 <= x 的下标):二分查找的变种,注意边界处理、相等时的收缩方向、以及不存在时的输出 -1。
3)数字金字塔(动态规划/DP):典型 DP 问题。从底层向上推,状态转移方程为 dp[i][j] = max(dp[i+1][j], dp[i+1][j+1]) + a[i][j],也可以自顶向下记忆化搜索。
💡 复习建议:重点掌握二维数组图形打印、二分查找边界处理、动态规划(数字三角形模型)。多画图,理清下标变化规律。
二、C++中学组——练习答案
F T F F T T T F F T
- 花园图案
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n; // 输入图案的大小,最终输出 n 行 n 列
// 外层循环控制行,i 表示当前行号,从 1 到 n
for (int i = 1; i <= n; i++) {
// 内层循环控制列,j 表示当前列号,从 1 到 n
for (int j = 1; j <= n; j++) {
// 满足以下任意一种情况,就输出 ''
// 1. i == 1:第一行,上边框
// 2. i == n:最后一行,下边框
// 3. j == 1:第一列,左边框
// 4. j == n:最后一列,右边框
// 5. i == j:从左上到右下的主对角线
// 6. i + j == n + 1:从右上到左下的副对角线
if (i == 1 || i == n || j == 1 || j == n || i == j || i + j == n + 1)
cout << '';
else
// 其他位置输出 '#'
cout << '#';
}
// 每一行输出完毕后换行
cout << endl;
}
return 0; // 程序正常结束
}
- 二分查找最后一个 ≤ x 的元素
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n; // 输入数组长度
// 使用 vector 存储数组,大小开到 n + 1,方便下标从 1 开始使用
vector<int> a(n + 1);
// 读入 n 个元素,存入 a[1] 到 a[n]
for (int i = 1; i <= n; i++) cin >> a[i];
int x;
cin >> x; // 输入要查找的目标值 x
// l 表示当前查找区间的左边界,r 表示右边界
// ans 用来记录最后一个 <= x 的元素下标,初始为 -1 表示还没找到
int l = 1, r = n, ans = -1;
// 当查找区间还存在时继续二分
while (l <= r) {
// 取中间位置
int mid = (l + r) / 2;
// 如果中间位置的元素 <= x
// 说明 mid 可能是一个答案,并且最后一个 <= x 的位置
// 一定在 mid 的右边或就是 mid
if (a[mid] <= x) {
ans = mid; // 先记录当前满足条件的下标
l = mid + 1; // 继续向右半区间查找更靠后的位置
} else {
// 如果 a[mid] > x,说明 mid 以及 mid 右边都不满足 <= x
// 答案只可能在左边
r = mid - 1;
}
}
// 输出最后一个 <= x 的元素下标
// 如果不存在,则输出 -1
cout << ans << endl;
return 0; // 程序正常结束
}
- 数字金字塔最大路径和
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int r;
cin >> r; // 输入数字金字塔的行数
// a[i][j] 存储数字金字塔中第 i 行第 j 列的数字
// 下标从 1 开始使用,所以大小开到 r + 1
vector<vector<int>> a(r + 1, vector<int>(r + 1, 0));
// dp[i][j] 表示从金字塔顶部走到位置 (i, j) 时能获得的最大路径和
vector<vector<int>> dp(r + 1, vector<int>(r + 1, 0));
// 读入数字金字塔
// 第 i 行一共有 i 个数字
for (int i = 1; i <= r; i++) {
for (int j = 1; j <= i; j++) {
cin >> a[i][j];
}
}
// 初始化顶点:从顶部走到 (1,1) 的最大路径和就是它本身
dp[1][1] = a[1][1];
// 从第 2 行开始进行动态规划
for (int i = 2; i <= r; i++) {
// 第 i 行有 i 个数字,列号 j 从 1 到 i
for (int j = 1; j <= i; j++) {
if (j == 1) {
// 最左边一列,只能从正上方 (i-1, j) 走下来
dp[i][j] = dp[i - 1][j] + a[i][j];
} else if (j == i) {
// 最右边一列,只能从左上方 (i-1, j-1) 走下来
dp[i][j] = dp[i - 1][j - 1] + a[i][j];
} else {
// 中间位置,可以从左上方 (i-1, j-1)
// 或正上方 (i-1, j) 两个方向走下来
// 取较大的路径和,再加上当前数字
dp[i][j] = max(dp[i - 1][j - 1], dp[i - 1][j]) + a[i][j];
}
}
}
// 在最后一行中寻找最大值
// 因为从顶部走到底部,最后一行每个位置都可能成为终点
int ans = 0;
for (int j = 1; j <= r; j++) {
ans = max(ans, dp[r][j]);
}
// 输出最大路径和
cout << ans << endl;
return 0; // 程序正常结束
}
这里空空如也















有帮助,赞一个