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

69 阅读3分钟

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

小R最近遇到了一个数组问题。他有一个包含 ( N ) 个元素的数组,记作 ( a_1, a_2, \ldots, a_N )。为了分析这个数组的特性,小R定义了两个函数 ( L(i) ) 和 ( R(i) ),并希望通过这两个函数来找到一些有趣的结论。本文将探讨如何帮助小R找到 ( MAX(i) = L(i) \times R(i) ) 的最大值,并提供详细的代码实现。

问题描述

给定一个包含 ( N ) 个元素的数组 ( a ),定义两个函数 ( L(i) ) 和 ( R(i) ) 如下:

  • ( 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 ) 最近的那个。 最终,小R定义 ( MAX(i) = L(i) \times R(i) ),他想知道在 ( 1 \leq i \leq N ) 的范围内,( MAX(i) ) 的最大值是多少。

解决方案

为了帮助小R找到 ( MAX(i) ) 的最大值,我们可以分以下几个步骤来实现:

  1. 计算 ( L(i) ) 和 ( R(i) )
    • 使用两个数组 leftright 分别存储 ( L(i) ) 和 ( R(i) ) 的值。
    • 从左到右遍历数组,计算每个位置的 ( L(i) )。
    • 从右到左遍历数组,计算每个位置的 ( R(i) )。
  2. 计算 ( MAX(i) )
    • 遍历数组,计算每个位置的 ( MAX(i) = L(i) \times R(i) )。
    • 记录并返回 ( MAX(i) ) 的最大值。

代码实现

public class Main {
    public static int solution(int n, int[] array) {
        int[] left = new int[n];
        int[] right = new int[n];
        
        // 计算 L(i)
        for (int i = 0; i < n; i++) {
            left[i] = 0;
            for (int j = i - 1; j >= 0; j--) {
                if (array[j] > array[i]) {
                    left[i] = j + 1;
                    break;
                }
            }
        }
        
        // 计算 R(i)
        for (int i = n - 1; i >= 0; i--) {
            right[i] = 0;
            for (int k = i + 1; k < n; k++) {
                if (array[k] > array[i]) {
                    right[i] = k + 1;
                    break;
                }
            }
        }
        
        // 计算 MAX(i) 的最大值
        int max = 0;
        for (int i = 0; i < n; i++) {
            int currentMax = left[i] * right[i];
            if (currentMax > max) {
                max = currentMax;
            }
        }
        
        return max;
    }
    public static void main(String[] args) {
        // 测试样例
        System.out.println(solution(5, new int[]{5, 4, 3, 4, 5}) == 8);  // 输出: true
        System.out.println(solution(6, new int[]{2, 1, 4, 3, 6, 5}) == 15);  // 输出: true
        System.out.println(solution(7, new int[]{1, 2, 3, 4, 5, 6, 7}) == 0);  // 输出: true
    }
}

代码解释

  1. 计算 ( L(i) )
    • 初始化 left 数组,所有元素初始值为0。
    • 从左到右遍历数组,对于每个位置 ( i ),从 ( i-1 ) 开始向左遍历,找到第一个大于 ( a[i] ) 的元素 ( j ),并记录 ( j+1 ) 为 ( L(i) )。
  2. 计算 ( R(i) )
    • 初始化 right 数组,所有元素初始值为0。
    • 从右到左遍历数组,对于每个位置 ( i ),从 ( i+1 ) 开始向右遍历,找到第一个大于 ( a[i] ) 的元素 ( k ),并记录 ( k+1 ) 为 ( R(i) )。
  3. 计算 ( MAX(i) ) 的最大值
    • 遍历数组,计算每个位置的 ( MAX(i) = L(i) \times R(i) )。
    • 记录并返回 ( MAX(i) ) 的最大值。

测试样例

  • 样例1n = 5, array = [5, 4, 3, 4, 5],输出:8
    • 解释:对于 ( i = 3 ),( L(3) = 2 ),( R(3) = 4 ),( MAX(3) = 2 \times 4 = 8 )。
  • 样例2n = 6, array = [2, 1, 4, 3, 6, 5],输出:15
    • 解释:对于 ( i = 2 ),( L(2) = 1 ),( R(2) = 5 ),( MAX(2) = 1 \times 5 = 5 );对于 ( i = 3 ),( L(3) = 2 ),( R(3) = 5 ),( MAX(3) = 2 \times 5 = 10 );对于 ( i = 4 ),( L(4) = 3 ),( R(4) = 6 ),( MAX(4) = 3 \times 6 = 18 )。
  • 样例3n = 7, array = [1, 2, 3, 4, 5, 6, 7],输出:0
    • 解释:数组是严格递增的,没有 ( j < i ) 使得 ( a[j] > a[i] ),也没有 ( k > i ) 使得 ( a[k] > a[i] ),因此 ( L(i) ) 和 ( R(i) ) 都为0,( MAX(i) ) 也为0。 通过上述方法,我们可以有效地帮助小R找到 ( MAX(i) ) 的最大值,确保在处理数组时算法的时间复杂度为 ( O(n^2) )。