F_JustWei's Studio.

5752. 子数组最小乘积的最大值

字数统计: 609阅读时长: 2 min
2021/05/09 Share

5752. 子数组最小乘积的最大值

一个数组的 最小乘积 定义为这个数组中 最小值 乘以 数组的

  • 比方说,数组 [3,2,5] (最小值是 2)的最小乘积为 2 * (3+2+5) = 2 * 10 = 20

给你一个正整数数组 nums ,请你返回 nums 任意 非空子数组最小乘积最大值 。由于答案可能很大,请你返回答案对 109 + 7 取余 的结果。

请注意,最小乘积的最大值考虑的是取余操作 之前 的结果。题目保证最小乘积的最大值在 不取余 的情况下可以用 64 位有符号整数 保存。

子数组 定义为一个数组的 连续 部分。

示例 1:

1
2
3
4
输入:nums = [1,2,3,2]
输出:14
解释:最小乘积的最大值由子数组 [2,3,2] (最小值是 2)得到。
2 * (2+3+2) = 2 * 7 = 14 。

示例 2:

1
2
3
4
输入:nums = [2,3,3,1,2]
输出:18
解释:最小乘积的最大值由子数组 [3,3] (最小值是 3)得到。
3 * (3+3) = 3 * 6 = 18 。

示例 3:

1
2
3
4
输入:nums = [3,1,5,6,4,2]
输出:60
解释:最小乘积的最大值由子数组 [5,6,4] (最小值是 4)得到。
4 * (5+6+4) = 4 * 15 = 60 。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 107

思路:

枚举数组中每个值 n ,并且以 n 作为子数组中的最小值,再乘以这个子数组的和。

C++代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
private:
typedef long long ll;
const int mod = 1e9+7;

public:
int maxSumMinProduct(vector<int>& nums) {
int n = nums.size();
// 前缀和
vector<ll> pre(n + 1);
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] + nums[i - 1];
}
// 单调栈
stack<int> s;
vector<int> left(n, 0);
vector<int> right(n, n - 1);
for (int i = 0; i < n; i++) {
// 如果当前元素比栈顶元素小,弹栈
while (!s.empty() && nums[i] < nums[s.top()]) {
// 这里的 right 是非严格定义的,right[i] 是右侧最近的小于等于 nums[i] 的元素下标
right[s.top()] = i - 1;
s.pop();
}
if (!s.empty()) {
// 这里的 left 是严格定义的,left[i] 是左侧最近的严格小于 nums[i] 的元素下标
left[i] = s.top() + 1;
}
s.push(i);
}

ll ans = 0;
for (int i = 0; i < n; i++) {
ans = max(ans, (pre[right[i] + 1] - pre[left[i]]) * nums[i]);
}
return ans % mod;
}
};
CATALOG
  1. 1. 5752. 子数组最小乘积的最大值
    1. 1.0.1. 示例 1:
    2. 1.0.2. 示例 2:
    3. 1.0.3. 示例 3:
    4. 1.0.4. 提示:
    5. 1.0.5. 思路:
    6. 1.0.6. C++代码: