给定一个数组序列, 需要求选出一个区间, 使得该区间是所有区间中经过如下计算的值最大的一个: 区间中的最小数 * 区间所有数的和最后程序输出经过计算后的最大值即可,
时间: 2024-04-01 10:31:50 浏览: 19
可以使用单调栈来解决这个问题。
具体的做法是,我们先用单调栈找出每个数左侧和右侧第一个小于它的数的位置,分别用 $left_i$ 和 $right_i$ 表示。这个过程可以参考 [84. 柱状图中最大的矩形](https://leetcode-cn.com/problems/largest-rectangle-in-histogram/)。
然后我们枚举每个数作为区间的最小值,假设当前枚举到的数是 $a_i$。那么它能扩展的左边界是 $left_i + 1$,右边界是 $right_i - 1$。于是我们就可以计算以 $a_i$ 为区间最小值的区间的最大值了。
具体的计算公式是:$a_i \times (sum_{left_i+1}^{right_i-1})$,其中 $sum_{left_i+1}^{right_i-1}$ 表示区间 $[left_i+1, right_i-1]$ 中所有数的和。
我们枚举所有的 $a_i$,取其中的最大值即可。
以下是参考代码:
```
public static long maxSum(int[] nums) {
int n = nums.length;
long[] left = new long[n], right = new long[n];
long[] sum = new long[n];
Deque<Integer> stack = new LinkedList<>();
// 计算 left 数组
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && nums[stack.peek()] >= nums[i]) {
stack.pop();
}
left[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(i);
}
// 计算 right 数组
stack.clear();
for (int i = n - 1; i >= 0; i--) {
while (!stack.isEmpty() && nums[stack.peek()] >= nums[i]) {
stack.pop();
}
right[i] = stack.isEmpty() ? n : stack.peek();
stack.push(i);
}
// 计算 sum 数组
for (int i = 0; i < n; i++) {
sum[i] = i == 0 ? nums[i] : sum[i - 1] + nums[i];
}
long ans = 0;
for (int i = 0; i < n; i++) {
long cur = nums[i] * (sum[(int) (right[i] - 1)] - (left[i] == -1 ? 0 : sum[(int) (left[i])]));
ans = Math.max(ans, cur);
}
return ans;
}
```
时间复杂度:$O(n)$。