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

96 阅读5分钟

在小 R 所面对的这个数组相关问题中,通过定义特殊的函数 L (i)、R (i) 进而得出 MAX (i),并最终寻求在特定范围内 MAX (i) 的最大值,这涉及到对数组元素的细致比较与分析。下面将对该问题及其求解代码展开详细探讨。

一、问题详细定义

小 R 拥有一个包含 N 个元素的数组,记为 a1, a2, …, aN。针对此数组,定义了两个函数 L (i) 和 R (i),其规则如下:

L (i) 函数:它表示满足 j <i 且 a [j] > a [i] 条件的最大的 j 值。若找不到符合条件的 j,则 L (i) = 0;若存在多个满足条件的 j,选取离 i 最近的那个。

R (i) 函数:它表示满足 k > i 且 a [k] > a [i] 条件的最小的 k 值。若找不到符合条件的 k,则 R (i) = 0;若存在多个满足条件的 k,选取离 i 最近的那个。

在此基础上,定义了 MAX (i) = L (i) * R (i),目标是找出在 1 < i < N 这个范围内,MAX (i) 的最大值。

二、分析思路

(一)双循环遍历更新数组思路

对于 L 数组的更新:外层循环遍历数组元素的索引 i(从 1 到 N),内层循环则从 i 开始递减遍历到 1(即for(int j = i; j >= 1; j--))。在每次内层循环中,检查是否满足 j <i 且 a [j - 1] > a [i - 1] 的条件,如果满足,则将 L [i] 赋值为 j,并通过break语句跳出内层循环,确保找到符合条件的离 i 最近的 j 值后就停止搜索。

对于 R 数组的更新:同样外层循环遍历索引 i(从 1 到 N),但内层循环是从 i 开始递增遍历到 N(即for(int k = i; k <= N; k++))。在每次内层循环中,检查是否满足 k > i 且 a [k - 1] > a [i - 1] 的条件,如果满足,则将 R [i] 赋值为 k,并跳出内层循环,以获取符合条件的离 i 最近的 k 值。

(二)计算 MAX (i) 并求最大值思路

在完成 L 数组和 R 数组的更新后,再次通过一个循环(for(int i = 1; i <= N; i++))遍历数组索引 i。对于每个 i,计算 MAX (i) 的值,即通过int tmp = L[i] * R[i];得到。然后将这个临时值 tmp 与当前记录的最大值 max 进行比较,通过max = Math.max(max, tmp);更新 max 的值,确保 max 始终记录着已经计算过的 MAX (i) 中的最大值。

三、代码解读与实现细节

public static int solution(int n, int[] array) {
// 初始化L数组和R数组,将所有元素初始化为0
int[] L = new int[n + 1], R = new int[n + 1];
int max = 0;
for (int i = 1; i <= n; i++) {
    L[i] = R[i] = 0;
}

// 更新L数组
for (int i = 1; i <= n; i++) {
    for (int j = i; j >= 1; j--){
        if (j < i && array[j - 1] > array[i - 1]) {
            L[i] = j;
            break;
        }
    }

    // 更新R数组
    for (int k = i; k <= n; k++){
        if (k > i && array[k - 1] > array[i - 1]) {
            R[i] = k;
            break;
        }
    }
}

// 计算MAX(i)并找出最大值
for (int i = 1; i <= n; i++) {
    int tmp = L[i] * R[i];
    max = Math.max(max, tmp);
}

return max;
}

四、复杂度分析

(一)时间复杂度

代码中主要的时间消耗在于更新 L 数组和 R 数组的两层嵌套循环以及后续计算 MAX (i) 并求最大值的循环。

对于更新 L 数组和 R 数组:外层循环都遍历了 N 次(从 1 到 N),内层循环在更新 L 数组时,最坏情况下每次外层循环的内层循环会执行 i 次(从 i 递减到 1),平均下来大约执行 N/2 次;同理,更新 R 数组时内层循环最坏情况下每次外层循环会执行 N - i + 1 次(从 i 递增到 N),平均下来也大约执行 N/2 次。所以更新 L 数组和 R 数组的时间复杂度大约为。

对于计算 MAX (i) 并求最大值的循环,它遍历了 N 次(从 1 到 N),但每次循环内部的操作时间复杂度为常数级,所以这部分时间复杂度为。

综合来看,整个代码的时间复杂度主要由更新 L 数组和 R 数组的操作决定,约为。

(二)空间复杂度

代码中定义了两个长度为 N + 1 的数组 L 和 R 来存储中间结果,以及一个变量 max 来存储最大值。 所以空间复杂度为,随着数组元素个数 N 的增加,所占用的存储空间也会相应增加。

五、总结与优化思考

通过上述代码的实现,能够按照小 R 定义的规则计算出在给定数组中 MAX (i) 的最大值。然而,从复杂度分析可知,时间复杂度在数组规模较大时可能导致性能不佳。对于优化,可以考虑以下几点:

时间复杂度优化:可以尝试使用一些数据结构如树状数组或线段树等来优化查找满足条件的 j 和 k 的过程,可能会将时间复杂度降低到甚至更低。例如,利用树状数组可以快速查询某个区间内大于给定值的元素位置,从而更高效地更新 L 数组和 R 数组。

空间复杂度优化:观察到在计算 MAX (i) 的过程中,实际上并不需要同时完整地保存 L 数组和 R 数组的所有值。可以考虑只使用几个变量来记录当前需要的信息,在计算过程中实时更新,这样有可能将空间复杂度降低到。

总之,理解小 R 对于数组特性分析的这种思路以及代码的实现方式,对于处理类似的基于数组元素关系定义函数并求最值的问题具有一定的借鉴意义,同时探索优化方案有助于提升算法在不同场景下的性能。