题解:学而思编程 演讲比赛

【题目来源】

学而思编程:演讲比赛

【题目描述】

小X的学校组织了一场演讲比赛,由 \(n\) 位评委对参赛选手进行打分。打分规则是去掉 \(n\) 位评委中最高得分和最低得分后,计算出剩余 \(n−2\) 位评委分数的平均值(保留两位小数)作为最后得分。

小X同学也积极参加了本次演讲比赛,请你帮小X计算一下他的最后得分。

【输入】

输入有 \(2\) 行,第 \(1\) 行,一个正整数 \(n\),表示有 \(n\) 位评委。

\(2\) 行,有 \(n\) 个正整数 \(p_i\),表示每一位评委的打分。

【输出】

输出一个数字,表示小X的最后得分,保留两位小数

【输入样例】

8
50 90 55 78 52 68 66 93

【输出样例】

68.17

【核心思想】

  1. 问题分析:给定 \(n\) 个评委打分 \(p_1, p_2, \ldots, p_n\),去掉一个最高分和一个最低分后,求剩余 \(n-2\) 个分数的平均值(保留两位小数)。这是一个极值过滤 + 统计计算问题,关键在于边读入边维护最大值、最小值和总和,避免二次遍历。

  2. 算法选择

    • 在线极值维护:在遍历过程中同步更新 \(mx\)(最大值)、\(mn\)(最小值)和 \(sum\)(总和),实现单遍扫描
    • 平均值计算:去掉两极值后,用 \((sum - mx - mn) / (n - 2)\) 计算平均值
  3. 关键步骤

    • 初始化\(mx = 0\)(最小可能分数),\(mn = 100\)(最大可能分数),\(sum = 0\)
    • 遍历评分(循环 \(n\) 次):
      • 读取 \(p_i\)
      • 累加总和:\(sum \leftarrow sum + p_i\)
      • 更新最大值:若 \(p_i > mx\),则 \(mx \leftarrow p_i\)
      • 更新最小值:若 \(p_i < mn\),则 \(mn \leftarrow p_i\)
    • 计算平均值
      • \(avg = 1.0 \times (sum - mx - mn) / (n - 2)\)
      • 使用 \(1.0 \times\) 强制浮点除法,避免整数截断
    • 输出结果:使用 %.2lf 格式输出 \(avg\),保留两位小数
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\),单遍扫描 \(n\) 个分数
    • 空间复杂度:\(O(1)\),仅使用 \(mx\)\(mn\)\(sum\) 三个变量,无需存储数组
  5. 在线统计的核心思想

    • 极值初始化技巧:根据题目约束(分数范围 \(0 \sim 100\)),\(mx\) 初始化为下界 \(0\)\(mn\) 初始化为上界 \(100\),确保第一个读入的分数能正确更新两者
    • 单遍扫描优势:边读入边计算,无需存储全部数据,节省空间且避免二次遍历
    • 浮点精度处理:通过 \(1.0 \times\)(double) 强制转换,确保除法为浮点运算;使用 printf("%.2lf") 精确控制输出小数位数
    • 去极值平均:去掉最高分和最低分是为了消除极端偏差,使最终得分更具代表性,计算时从总和中直接减去两个极值,避免单独存储中间数组
    • 适用于实时统计、流式数据处理、带过滤条件的平均值计算类问题

【解题思路】

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;

int main()
{
    // 输入数据个数n
    int n;
    cin >> n;

    // 初始化最大值、最小值和总和
    int mx = 0;      // 存储最大值,初始设为最小值
    int mn = 100;    // 存储最小值,初始设为最大值
    int sum = 0;     // 存储所有数的总和

    // 循环读取n个数
    for (int i = 1; i <= n; i++)
    {
        int p;
        cin >> p;    // 读取当前数

        // 累加到总和
        sum += p;

        // 更新最大值
        if (p > mx)
        {
            mx = p;
        }

        // 更新最小值
        if (p < mn)
        {
            mn = p;
        }
    }

    // 计算去掉一个最高分和一个最低分后的平均分
    // 注意:n-2是除数,因为去掉了两个数
    double avg = 1.0 * (sum - mx - mn) / (n - 2);

    // 输出结果,保留两位小数
    printf("%.2lf\n", avg);

    return 0;
}

【运行结果】

8
50 90 55 78 52 68 66 93
68.17
posted @ 2026-07-05 17:17  团爸讲算法  阅读(8)  评论(0)    收藏  举报