题解:学而思编程 演讲比赛
【题目来源】
学而思编程:演讲比赛
【题目描述】
小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
【核心思想】
-
问题分析:给定 \(n\) 个评委打分 \(p_1, p_2, \ldots, p_n\),去掉一个最高分和一个最低分后,求剩余 \(n-2\) 个分数的平均值(保留两位小数)。这是一个极值过滤 + 统计计算问题,关键在于边读入边维护最大值、最小值和总和,避免二次遍历。
-
算法选择:
- 在线极值维护:在遍历过程中同步更新 \(mx\)(最大值)、\(mn\)(最小值)和 \(sum\)(总和),实现单遍扫描
- 平均值计算:去掉两极值后,用 \((sum - mx - mn) / (n - 2)\) 计算平均值
-
关键步骤:
- 初始化:\(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\),保留两位小数
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),单遍扫描 \(n\) 个分数
- 空间复杂度:\(O(1)\),仅使用 \(mx\)、\(mn\)、\(sum\) 三个变量,无需存储数组
-
在线统计的核心思想:
- 极值初始化技巧:根据题目约束(分数范围 \(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
浙公网安备 33010602011771号