问题描述
对于一个有 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) 的最大值。
解题思路
-
计算左邻居
L(i):- 使用一个栈来存储数组元素的索引,栈中的元素按照数组值的递减顺序排列。
- 遍历数组,对于每个元素,如果栈不为空且栈顶元素的值小于当前元素的值,那么栈顶元素就是当前元素的左邻居。
- 如果栈为空,或者栈顶元素的值大于等于当前元素的值,那么当前元素没有左邻居,
L(i) = 0。
-
计算右邻居
R(i):- 类似地,使用一个栈来存储数组元素的索引,栈中的元素按照数组值的递减顺序排列。
- 从数组的末尾开始向前遍历,对于每个元素,如果栈不为空且栈顶元素的值小于当前元素的值,那么栈顶元素就是当前元素的右邻居。
- 如果栈为空,或者栈顶元素的值大于等于当前元素的值,那么当前元素没有右邻居,
R(i) = 0。
-
计算
MAX(i):- 对于每个元素,计算
MAX(i) = L(i) * R(i)。 - 遍历所有元素,找到
MAX(i)的最大值。
- 对于每个元素,计算
解题过程
-
初始化数组
L和R:- 创建两个长度为
n的数组L和R,用于存储每个元素的左邻居和右邻居的索引。
- 创建两个长度为
-
计算
L(i):- 使用一个栈来存储索引。
- 从左到右遍历数组,对于每个元素,如果栈不为空且栈顶元素的值小于当前元素的值,那么弹出栈顶元素。
- 如果栈为空,或者栈顶元素的值大于等于当前元素的值,那么当前元素的左邻居就是栈顶元素的索引(如果栈不为空)。
- 将当前元素的索引入栈。
-
计算
R(i):- 清空栈,然后从右到左遍历数组。
- 对于每个元素,如果栈不为空且栈顶元素的值小于当前元素的值,那么弹出栈顶元素。
- 如果栈为空,或者栈顶元素的值大于等于当前元素的值,那么当前元素的右邻居就是栈顶元素的索引(如果栈不为空)。
- 将当前元素的索引入栈。
-
计算
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) 的最大值。