最大乘积问题 | 豆包MarsCode AI刷题

61 阅读3分钟

最大乘积问题

一、问题重现

问题描述

对于一个有 N 个元素的数组,包含如下的元素 a1, a2, ..., an,我们定义了两个函数:

  • L(i) = j 需要满足的条件如下:

    • j < i
    • a[j] > a[i]
    • 如果找不到 j 的话,那么 L(i) = 0;如果有多个 j 的话,选择离 i 最近的那一个
  • R(i) = k 需要满足的条件如下:

    • k > i
    • a[k] > a[i]
    • 如果找不到 k 的话,那么 R(i) = 0;如果有多个 k 的话,选择离 i 最近的那一个

最后,我们定义 MAX(i) = L(i) * R(i),我们需要找到 MAX(i) 的最大值,其中 1 <= i <= N。

输入格式

总共有两行,第一行是数组长度 N,第二个是空格分割的所有数组的内容。

输出格式

输出 MAX(i) 的最大值。

输入样例

5
5 4 3 4 5

输出样例

8

解释说明

  • L(1) = 0,所以 MAX(1) = 0
  • L(2) = 1, R(2) = 5,所以 MAX(2) = 1 * 5 = 5
  • L(3) = 2, R(3) = 4,所以 MAX(3) = 2 * 4 = 8
  • L(4) = 1, R(4) = 5,所以 MAX(4) = 1 * 5 = 5
  • R(5) = 0,所以 MAX(5) = 0

数据范围

  • 1<=N<=1051<=N<=105
  • 1<=a[i]<=1091<=a[i]<=109

二、解题思路

问题理解

我们需要找到数组中每个元素的 L(i) 和 R(i),然后计算 MAX(i) = L(i) * R(i),并找出 MAX(i) 的最大值。

  • L(i) 是小于 i 且大于 a[i] 的最近元素的索引。
  • R(i) 是大于 i 且大于 a[i] 的最近元素的索引。

数据结构选择

由于我们需要频繁地查找和更新 L(i) 和 R(i),而这里寻找 L(i) 和 R(i)的过程是单调对比的,所以并不需要记录每一层的 L(i) 和 R(i),保持最大值即可。

算法步骤

  1. 初始化

    • 定义一个变量 ans 用于存储 MAX(i) 的最大值,初始值为 0
  2. 遍历数组

    • 使用外层循环遍历数组中的每个元素 a[i]
  3. 计算 L(i)

    • 对于每个元素 a[i],使用内层循环从 i-1 开始向左遍历,找到第一个大于 a[i] 的元素 a[j],并记录其索引 j + 1 作为 L
  4. 计算 R(i)

    • 对于每个元素 a[i],使用内层循环从 i+1 开始向右遍历,找到第一个大于 a[i] 的元素 a[k],并记录其索引 k + 1 作为 R
  5. 更新 ans

    • 计算 L * R,并与当前的 ans 进行比较,更新 ans 为较大的值。
  6. 返回结果

    • 遍历结束后,返回 ans 作为最终结果。

三、代码实现

int solution(int n, std::vector<int> array) {
    int ans = 0;
    for(int i = 0; i < n; ++i) {
        int L = 0, R = 0;
        for(int j = i-1; j >= 0; --j) {
            if(array[j] > array[i]){
                L = j + 1;
                break;
            }
        }
        for(int k = i + 1; k < n; ++k) {
            if(array[k] > array[i]){
                R = k + 1;
                break;
            }
        }
        ans = L * R > ans ? L * R : ans;
    }
    return ans;
}

四、算法复杂度分析

  • 时间复杂度

    • 外层循环遍历数组的时间复杂度为 O(N)
    • 内层循环分别向左和向右查找 L(i) 和 R(i),最坏情况下每个内层循环的时间复杂度为 O(N)
    • 因此,总的时间复杂度为 O(N^2)
  • 空间复杂度

    • 只使用了常数级别的额外空间,空间复杂度为 O(1)