📜  门| GATE CS 2020 |第 39 题(1)

📅  最后修改于: 2023-12-03 15:42:12.303000             🧑  作者: Mango

GATE CS 2020 | 第 39 题

本题来自计算机科学领域中的最重要的考试之一,即“门牌 CS 2020”。此题考察了程序员的算法设计和分析能力。

题目描述

给定一个包含 $n$ 个整数的数组 $A$,请编写一个时间复杂度为 $O(n)$ 的算法来找到数组中平均数最大的非空子数组。平均数为子数组中所有元素的平均值。

输入格式

输入的第一行包含一个整数 $n$,表示数组 $A$ 中元素的个数。

接下来 $n$ 行,每行包含一个整数 $A_i$。

输出格式

输出的第一行应包含找到的非空子数组的平均数。

接下来的一行,输出找到的平均数最大的子数组的前后下标(子数组从 0 开始)。

示例

输入:

5
1
-2
3
-1
2

输出:

2.000000
0 4
解答结构

题目要求我们设计一个时间复杂度为 $O(n)$ 的算法,来找到数组中平均数最大的非空子数组。 这是一个比较典型的求最优解问题,对经典的优化求解问题,我们可以使用贪心、动态规划等算法。在本题中,我们采用贪心算法来解决。

我们首先考虑在一个非空数组区间中寻找平均数最大的子数组,假设这个数组区间是 $[l,r]$,那么它的平均数就是 $\frac{\sum_{i=l}^{r} A[i]}{r-l+1}$。 由于我们要想让平均数最大,就要尽可能地让 $\sum_{i=l}^{r} A[i]$ 最大。但是,如果我们直接暴力地考虑所有子数组的和,时间复杂度显然是 $O(n^2)$ 的,因此我们需要一个更优秀的方法来解决问题。

我们考虑固定左端点 $l$,然后找右端点 $r$,使得 $[l,r]$ 中的数组元素之和最大,此时就可以根据 $r-l+1$ 计算出其平均值。由于我们希望数组中平均数最大,因此可以采用类似于“滑动窗口”算法的方法:既然 $[l,r]$ 是该数组中和最大的子区间,那么对于 $l'\gt l$ 而言,一定有 $\sum_{i=l}^{r} A[i] ≤ \sum_{i=l'}^{r} A[i]$。因此,我们可以每次令左端点 $l$ 右移,并依次更新 $[l,r]$ 的和,找到最大和的子数组。

接下来,我们来看代码实现。