Files

10 KiB
Raw Permalink Blame History

第11课综合练习

教学目标

  • 混合题型训练,覆盖一二级核心知识点
  • 查漏补缺,找到薄弱环节
  • 提高解题速度和准确率

核心考点:混合题的拆解与算法组合

考什么

综合题不会直接告诉你使用哪一课的知识,而是把输入输出、分支、循环、数组、字符串等组合起来。考试重点是从题意中识别若干小任务,为每个小任务选择已经学过的代码模式,再按正确顺序连接。

必须理解

先把题目拆成“输入什么→处理什么→输出什么”三段。处理部分继续拆成动作,例如“遍历数组→筛选满足条件的元素→打擂台求最值→输出下标”。每个动作只解决一个问题,再把前一步结果交给下一步。读到“每个”通常想到遍历,读到“最大/最小”想到打擂台,读到“出现次数”想到计数,读到“如果/否则”想到分支。组合算法时要明确数据在各步骤中的含义,不能边读题边盲写代码。

核心写法

1. 圈出输入、输出和数据范围
2. 把处理过程拆成若干小任务
3. 为每个小任务选择代码模板
4. 确定各步骤先后与中间变量
5. 写代码后用样例和边界值检查

例如“找数组中出现次数最多的数”可拆成:数组输入 + 频次统计 + 打擂台 + 输出答案。

常见错误

  • 一看到长题目就直接写代码,没有先拆任务。
  • 只完成主算法,漏掉输入格式、并列规则或输出顺序。
  • 不区分中间变量的含义,把下标、数值和次数混用。
  • 只测试题目样例,不测试空边界、最小值、最大值或并列情况。

判断是否掌握

拿到一道混合题,能在动手前写出清晰的三到五步伪代码,并能指出每一步使用了哪种基础结构或算法模板。


题目一:成绩等级判断(分支 + 输入输出)

核心代码(一句话)

多分支判断的核心:if - else if - else 链条,从大到小或从小到大依次判断,每种情况一个分支。

自然语言思路

输入一个 0-100 的成绩输出对应的等级90-100 → A80-89 → B70-79 → C60-69 → D60以下 → E。

第一步,接收输入 score。 第二步,从高分往低分判断:if (score >= 90) → Aelse if (score >= 80) → B依次类推。 第三步,最后一个 else 兜底,对应 E 等级。 第四步,注意判断顺序:如果从小到大判断(先 score < 60),要看清楚边界别重叠。

GESP 考试中这类题会以"程序阅读"或"编程题"形式出现,要注意 if-else 的匹配逻辑。

伪代码

1. 输入 score
2. if score >= 90     输出 "A"
3. else if score >= 80 输出 "B"
4. else if score >= 70 输出 "C"
5. else if score >= 60 输出 "D"
6. else               输出 "E"

真实代码

#include <iostream>
using namespace std;

int main() {
    int score;
    cin >> score;

    if (score >= 90) {
        cout << "A" << endl;
    } else if (score >= 80) {
        cout << "B" << endl;
    } else if (score >= 70) {
        cout << "C" << endl;
    } else if (score >= 60) {
        cout << "D" << endl;
    } else {
        cout << "E" << endl;
    }
    return 0;
}

注意点

  1. 判断顺序很重要:从大到小写最清晰,因为 else if 意味着"前面条件都不满足"。如果从小到大写,要注意边界。
  2. 边界值90 是 A89 是 B。如果写成 score > 90 就会把 90 分的人划到 B检查时要留意。
  3. 输入范围:题目保证输入在 0-100但实际考试中如果输入 101 按上面代码会输出 "A"(因为 ≥90。严谨的做法是加范围检查。

题目二:数组求最大值及下标(数组 + 循环 + 打擂台)

核心代码(一句话)

带下标记录的打擂台:用一个变量记最大值,另一个变量记下标,每次换擂主时两个一起更新。

自然语言思路

输入 n 个数,输出最大值和它第一次出现的下标。

第一步,读入数组。 第二步,设 maxVal = arr[0]maxIndex = 0,两个变量一起初始化为第一个元素的值和下标。 第三步,从 i = 1 开始遍历,如果 arr[i] > maxVal(严格大于),则同时更新 maxVal = arr[i]maxIndex = i。 第四步,遍历结束,输出最大值和下标。

注意是"严格大于" >,不是 >=。如果写成 >=,遇到重复最大值时会记录最后一次出现的位置。

伪代码

1. 输入 n
2. 读入数组 arr[n]
3. maxVal = arr[0], maxIndex = 0
4. for i = 1 到 n-1
5.     if arr[i] > maxVal    // 严格大于
6.         maxVal = arr[i]
7.         maxIndex = i
8. 输出 maxVal 和 maxIndex

真实代码

#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int arr[n];
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }

    int maxVal = arr[0];
    int maxIndex = 0;
    for (int i = 1; i < n; i++) {
        if (arr[i] > maxVal) {
            maxVal = arr[i];
            maxIndex = i;
        }
    }

    cout << "最大值:" << maxVal << ",下标:" << maxIndex << endl;
    return 0;
}

注意点

  1. > vs >=:用 > 保留第一次出现的下标,用 >= 保留最后一次出现的下标。看题目要求。
  2. maxIndex 初始值:必须和 maxVal 的初始值对应。如果 maxVal 从 arr[0] 开始maxIndex 就是 0。
  3. 循环从 1 开始:因为 arr[0] 已经是初始擂主了。

题目三字符串分类统计string + 字符判断 + 多计数器)

核心代码(一句话)

字符串分类统计的核心:遍历 + 多分支判断 + 多个计数器,每个 if 分支对应一个计数器。

自然语言思路

输入一行字符串,统计其中大写字母、小写字母、数字、其他字符(含空格)各有多少个。

第一步,用 getline(cin, s) 读入整行(因为可能含空格)。 第二步,设四个计数器 upper, lower, digit, other 都初始为 0。 第三步,遍历每个字符 s[i],用 isupperislowerisdigit 判断类型,对应计数器 +1。 第四步,都不满足的归入 other。 第五步,输出四个统计结果。 第六步,注意空格也算"其他",如果不想算空格可以先单独判断 s[i] == ' '

伪代码

1. getline 读取字符串 s
2. upper = 0, lower = 0, digit = 0, other = 0
3. for i = 0 到 s.length()-1
4.     if isupper(s[i])     upper++
5.     else if islower(s[i]) lower++
6.     else if isdigit(s[i]) digit++
7.     else                 other++
8. 输出四个计数结果

真实代码

#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int main() {
    string s;
    getline(cin, s);

    int upper = 0, lower = 0, digit = 0, other = 0;
    for (int i = 0; i < s.length(); i++) {
        if (isupper(s[i])) {
            upper++;
        } else if (islower(s[i])) {
            lower++;
        } else if (isdigit(s[i])) {
            digit++;
        } else {
            other++;
        }
    }

    cout << "大写:" << upper
         << ",小写:" << lower
         << ",数字:" << digit
         << ",其他:" << other << endl;
    return 0;
}

注意点

  1. getline 不是 cincin >> s 遇空格就停,"Hello World" 只会读到 "Hello"。
  2. isupper 等函数需要 <cctype>:别忘了加这个头文件。
  3. else 分支的归属:空格、标点符号都会进 other。如果题目要求单独统计空格,需要在 else 前加 else if (s[i] == ' ')
  4. 空的字符串:如果什么都没输入,四个计数器都是 0输出全零不会出错。

限时练习(课堂完成)

练习组一(限时 30 分钟)

  1. 输入两个数,输出较大的数(基础输入输出 + if
  2. 输入 n输出 n 的阶乘 1 × 2 × 3 × ... × n(循环 + 累乘)
  3. 输入一个字符串判断是否为回文string + 循环)

练习组二(限时 30 分钟)

  1. 输入 n 个数,求平均值(数组 + 求和 + 浮点数)
  2. 找出 100 以内的所有素数(循环 + 判断素数)
  3. 输入一个正整数,输出它的逆序数(如 12345 → 54321数位拆解

练习组三(限时 30 分钟)

  1. 输入年份,判断是否为闰年(能被 4 整除且不能被 100 整除,或能被 400 整除)
  2. 输入 n打印左下直角三角形嵌套循环
  3. 输入一个字符串统计其中数字的个数string + isdigit

解题技巧

1. 仔细审题

  • 看清输入输出格式(空格、换行、大小写)
  • 注意数据范围(决定用 int 还是 long long
  • 理解题目要求(从小到大输出还是从大到小)

2. 先想后写

  • 在草稿纸上写出核心步骤
  • 用伪代码搭好骨架
  • 再动手写真实代码

3. 测试验证

  • 先用样例数据测试
  • 再试边界情况0、1、最大值、最小值
  • 检查输出格式是否完全一致

4. 时间管理

  • 先做简单的题,拿稳基础分
  • 不会的题先跳过,不要死磕
  • 留 10 分钟检查

常见错误检查清单

在交卷前逐条检查:

  • 头文件是否包含(<iostream><string><cmath><cctype> 等)
  • using namespace std; 是否写了
  • 变量是否初始化(特别是累加器、计数器)
  • 数组下标是否越界(从 0 到 n-1
  • 循环边界是否正确(< vs <=
  • 输出格式是否正确(空格、换行、中文/英文标点)
  • 是否处理了边界情况0、1、负数等
  • 整数除法是否需要转浮点数
  • string 输入是否用了 getline(含空格时)

本课打油诗

综合练习查漏洞,各种题型过一遍。 先审题意后动手,伪代码里思路现。 边界条件要想全,样例测完再交卷。 时间分配有策略,不会先跳回头见。


课后作业

  1. 补完课堂限时练习中未完成的题目
  2. 整理自己的错题本,写出错误原因和正确解法
  3. 在洛谷上完成 GESP 一级真题中的 3 道编程题