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

31 阅读4分钟

问题描述

对于一个有 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### 题目分析

题目要求我们对一个给定的数组,计算每个元素的左邻居和右邻居(如果存在的话),这些邻居的值必须大于当前元素的值。然后,我们定义一个新的函数 MAX(i) = L(i) * R(i),其中 L(i) 是第 i 个元素的左邻居的索引,R(i) 是第 i 个元素的右邻居的索引。我们的目标是找到 MAX(i) 的最大值。

解题思路

  1. 计算左邻居 L(i)

    • 使用一个栈来存储数组元素的索引,栈中的元素按照数组值的递减顺序排列。
    • 遍历数组,对于每个元素,如果栈不为空且栈顶元素的值小于当前元素的值,那么栈顶元素就是当前元素的左邻居。
    • 如果栈为空,或者栈顶元素的值大于等于当前元素的值,那么当前元素没有左邻居,L(i) = 0
  2. 计算右邻居 R(i)

    • 类似地,使用一个栈来存储数组元素的索引,栈中的元素按照数组值的递减顺序排列。
    • 从数组的末尾开始向前遍历,对于每个元素,如果栈不为空且栈顶元素的值小于当前元素的值,那么栈顶元素就是当前元素的右邻居。
    • 如果栈为空,或者栈顶元素的值大于等于当前元素的值,那么当前元素没有右邻居,R(i) = 0
  3. 计算 MAX(i)

    • 对于每个元素,计算 MAX(i) = L(i) * R(i)
    • 遍历所有元素,找到 MAX(i) 的最大值。

解题过程

  1. 初始化数组 LR

    • 创建两个长度为 n 的数组 L 和 R,用于存储每个元素的左邻居和右邻居的索引。
  2. 计算 L(i)

    • 使用一个栈来存储索引。
    • 从左到右遍历数组,对于每个元素,如果栈不为空且栈顶元素的值小于当前元素的值,那么弹出栈顶元素。
    • 如果栈为空,或者栈顶元素的值大于等于当前元素的值,那么当前元素的左邻居就是栈顶元素的索引(如果栈不为空)。
    • 将当前元素的索引入栈。
  3. 计算 R(i)

    • 清空栈,然后从右到左遍历数组。
    • 对于每个元素,如果栈不为空且栈顶元素的值小于当前元素的值,那么弹出栈顶元素。
    • 如果栈为空,或者栈顶元素的值大于等于当前元素的值,那么当前元素的右邻居就是栈顶元素的索引(如果栈不为空)。
    • 将当前元素的索引入栈。
  4. 计算 MAX(i)

    • 遍历数组,对于每个元素,计算 MAX(i) = L(i) * R(i)
    • 找到 MAX(i) 的最大值。

代码实现

java
import java.util.Stack;

public class Main {
    public static int solution(int n, int[] array) {
        int[] L = new int[n];
        int[] R = new int[n];

        // 计算 L(i)
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < n; i++) {
            while (!stack.isEmpty() && array[stack.peek()] <= array[i]) {
                stack.pop();
            }
            L[i] = stack.isEmpty() ? 0 : stack.peek() + 1; // +1 to convert to 1-based index
            stack.push(i);
        }

        // 计算 R(i)
        stack.clear();
        for (int i = n - 1; i >= 0; i--) {
            while (!stack.isEmpty() && array[stack.peek()] <= array[i]) {
                stack.pop();
            }
            R[i] = stack.isEmpty() ? 0 : stack.peek() + 1; // +1 to convert to 1-based index
            stack.push(i);
        }

        // 计算 MAX(i)
        int maxValue = 0;
        for (int i = 0; i < n; i++) {
            maxValue = Math.max(maxValue, L[i] * R[i]);
        }

        return maxValue;
    }

    public static void main(String[] args) {
        // 添加测试用例
        System.out.println(solution(5, new int[]{5, 4, 3, 4, 5}) == 8); // 应该返回 8
        System.out.println(solution(6, new int[]{1, 2, 3, 4, 5, 6}) == 0); // 测试单调递增
        System.out.println(solution(6, new int[]{6, 5, 4, 3, 2, 1}) == 0); // 测试单调递减
        System.out.println(solution(5, new int[]{1, 3, 2, 4, 5}) == 6); // 测试混合情况
    }
}

结论

通过上述分析和代码实现,我们可以有效地解决这个问题。代码中使用了栈来存储索引,以便快速找到每个元素的左邻居和右邻居。最后,我们遍历数组,计算 MAX(i) 的最大值。