跳转至

打擂台:求最大值和最小值

什么时候用?

看到“最高分”“最低温度”“最大值”“最小值”,可以想到打擂台。

先会:输入、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;
}

输入:

4
6 3 9 7

输出:

9 3

为什么不用 0 当第一个擂主?

如果所有数都是 -8 -3 -10,把最大值初始化成 0,就会错误地输出没出现过的 0。

让第一个输入的数当擂主,不用猜数据有多大或多小。但是必须保证至少有一个数;n = 0 时没有最大值或最小值,需要按题意另行处理。

本例只保存当前最值,不需要把所有数字存起来。比较次数随 n 增长,时间复杂度是 O(n),额外空间是 O(1)。

如果还要知道“第几个”?

代码片段:先设 int pos = 1;,更新最大值时同时更新位置。

if (x > maxn) {
    maxn = x;
    pos = i;
}

用 >,并列最大值保留最早的位置;用 >=,保留最后的位置。题目要求哪个,就选哪个。

先练再看答案

  1. 只有一个数 7,最大值和最小值分别是多少?循环会执行吗?
  2. 输入 -8 -3 -10,应该输出什么?
  3. 有 6 9 9 2,要保留第一个最高分的位置,应该用 > 还是 >=?
答案
  1. 都是 7,循环一次也不执行。
  2. 输出 -3 -10。
  3. 用 >,得到位置 2。

下一步:枚举可以产生一个个候选答案,打擂台可以从中选出最好的一项。