打擂台:求最大值和最小值¶
什么时候用?¶
看到“最高分”“最低温度”“最大值”“最小值”,可以想到打擂台。
先会:输入、if、for 循环。不需要先学数组。
像比赛一样,一个一个比较¶
有 4 个数:6 3 9 7。先请第一个数 6 当“擂主”。后面的数依次挑战,谁大谁留下。
| 这次读到的数 | 发生了什么 | 目前最大值 |
|---|---|---|
6 |
第一个数,先当擂主 | 6 |
3 |
比擂主小,不换 | 6 |
9 |
比擂主大,换擂主 | 9 |
7 |
比擂主小,不换 | 9 |
maxn 记住“到目前为止最大的数”。要找最小值,就把比较方向反过来。
完整例子:同时找最大值和最小值¶
第一行输入 n,第二行输入 n 个整数。约定 1 <= n <= 100000,每个数在 -10^9 到 10^9 之间。输出最大值、最小值,用空格隔开。
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
long long x;
cin >> x; // 第一个数已经读过了
long long maxn = x, minn = x;
for (int i = 2; i <= n; i++) {
cin >> x;
if (x > maxn) {
maxn = x;
}
if (x < minn) {
minn = x;
}
}
cout << maxn << ' ' << minn << '\n';
return 0;
}
输入:
输出:
为什么不用 0 当第一个擂主?¶
如果所有数都是 -8 -3 -10,把最大值初始化成 0,就会错误地输出没出现过的 0。
让第一个输入的数当擂主,不用猜数据有多大或多小。但是必须保证至少有一个数;n = 0 时没有最大值或最小值,需要按题意另行处理。
本例只保存当前最值,不需要把所有数字存起来。比较次数随 n 增长,时间复杂度是 O(n),额外空间是 O(1)。
如果还要知道“第几个”?¶
代码片段:先设 int pos = 1;,更新最大值时同时更新位置。
用 >,并列最大值保留最早的位置;用 >=,保留最后的位置。题目要求哪个,就选哪个。
先练再看答案¶
- 只有一个数
7,最大值和最小值分别是多少?循环会执行吗? - 输入
-8 -3 -10,应该输出什么? - 有
6 9 9 2,要保留第一个最高分的位置,应该用>还是>=?
答案
- 都是
7,循环一次也不执行。 - 输出
-3 -10。 - 用
>,得到位置2。
下一步:枚举可以产生一个个候选答案,打擂台可以从中选出最好的一项。