Maximum Subarray Min-Product

medium array monotonic stack prefix sum

Problem

The min-product of a contiguous subarray is its minimum element multiplied by the sum of all its elements. Given an array of positive integers nums, return the largest min-product over every possible subarray, taken modulo 10^9 + 7. The maximum itself is found before applying the modulo.

Inputnums = [1, 2, 3, 2]
Output14
The subarray [2, 3, 2] has minimum 2 and sum 7, so its min-product is 2 × 7 = 14, the best of any subarray.

def maxSumMinProduct(nums):
    MOD = 10**9 + 7
    n = len(nums)
    prefix = [0] * (n + 1)
    for i in range(n):
        prefix[i + 1] = prefix[i] + nums[i]
    best = 0
    st = []
    for i in range(n + 1):
        cur = nums[i] if i < n else 0
        while st and nums[st[-1]] >= cur:
            j = st.pop()
            left = st[-1] + 1 if st else 0
            total = prefix[i] - prefix[left]
            best = max(best, nums[j] * total)
        st.append(i)
    return best % MOD
function maxSumMinProduct(nums) {
  const MOD = 1000000007n;
  const n = nums.length;
  const prefix = new Array(n + 1).fill(0n);
  for (let i = 0; i < n; i++) prefix[i + 1] = prefix[i] + BigInt(nums[i]);
  let best = 0n;
  const st = [];
  for (let i = 0; i <= n; i++) {
    const cur = i < n ? nums[i] : 0;
    while (st.length && nums[st[st.length - 1]] >= cur) {
      const j = st.pop();
      const left = st.length ? st[st.length - 1] + 1 : 0;
      const total = prefix[i] - prefix[left];
      const prod = BigInt(nums[j]) * total;
      if (prod > best) best = prod;
    }
    st.push(i);
  }
  return Number(best % MOD);
}
class Solution {
    public int maxSumMinProduct(int[] nums) {
        final long MOD = 1000000007L;
        int n = nums.length;
        long[] prefix = new long[n + 1];
        for (int i = 0; i < n; i++) prefix[i + 1] = prefix[i] + nums[i];
        long best = 0;
        Deque<Integer> st = new ArrayDeque<>();
        for (int i = 0; i <= n; i++) {
            int cur = i < n ? nums[i] : 0;
            while (!st.isEmpty() && nums[st.peek()] >= cur) {
                int j = st.pop();
                int left = st.isEmpty() ? 0 : st.peek() + 1;
                long total = prefix[i] - prefix[left];
                best = Math.max(best, (long) nums[j] * total);
            }
            st.push(i);
        }
        return (int) (best % MOD);
    }
}
int maxSumMinProduct(vector<int>& nums) {
    const long long MOD = 1000000007LL;
    int n = (int) nums.size();
    vector<long long> prefix(n + 1, 0);
    for (int i = 0; i < n; i++) prefix[i + 1] = prefix[i] + nums[i];
    long long best = 0;
    stack<int> st;
    for (int i = 0; i <= n; i++) {
        int cur = i < n ? nums[i] : 0;
        while (!st.empty() && nums[st.top()] >= cur) {
            int j = st.top(); st.pop();
            int left = st.empty() ? 0 : st.top() + 1;
            long long total = prefix[i] - prefix[left];
            best = max(best, (long long) nums[j] * total);
        }
        st.push(i);
    }
    return (int) (best % MOD);
}
Time: O(n) Space: O(n)