子数组最小乘积的最大值
难度:
标签:
题目描述
代码结果
运行时间: 235 ms, 内存: 32.3 MB
/*
题目思路:
1. 使用Java Stream处理时,重点在于如何高效计算子数组的和及最小值。
2. 可以考虑先计算每个元素作为最小值时的左、右边界,然后通过stream计算总和。
3. 由于stream主要用在简化代码结构上,这里示例代码尽量精简。
*/
import java.util.*;
public class Solution {
public int maxSumMinProduct(int[] nums) {
int MOD = 1_000_000_007;
int n = nums.length;
long[] prefixSum = new long[n + 1];
for (int i = 0; i < n; i++) {
prefixSum[i + 1] = prefixSum[i] + nums[i];
}
Stack<Integer> stack = new Stack<>();
long maxProduct = 0;
for (int i = 0; i <= n; i++) {
while (!stack.isEmpty() && (i == n || nums[stack.peek()] > nums[i])) {
int minIndex = stack.pop();
int left = stack.isEmpty() ? -1 : stack.peek();
long sum = prefixSum[i] - prefixSum[left + 1];
maxProduct = Math.max(maxProduct, sum * nums[minIndex]);
}
stack.push(i);
}
return (int) (maxProduct % MOD);
}
}
解释
方法:
这个题解采用了单调栈和前缀和的方法来求解。首先,使用单调栈来找到每个元素左侧第一个严格小于它的元素的位置和右侧第一个小于等于它的元素的位置。这样,对于每个元素,我们就可以确定一个区间,使得该元素是区间内的最小值。然后,使用前缀和数组来快速计算这些区间的元素和。最后,遍历每个元素,计算以它为最小值的区间的最小乘积,并更新最大值。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在题解中提到使用单调栈找到每个元素左侧第一个严格小于它和右侧第一个小于等于它的元素的位置,这种方法对于找到这些位置的准确性如何保证?
▷🦆
题解中的单调栈是如何工作的,能否详细解释一下为什么在遇到当前元素小于栈顶元素时,需要弹出栈顶元素?
▷🦆
题解中计算最小乘积时,最后返回的结果进行了取余操作,这里为什么要进行取余,直接返回最大值不可以吗?
▷