Maximum Subarray Min-Product
MedPrompt
The min-product of an array is equal to the minimum value in the array multiplied by the array's sum.
- For example, the array
[3,2,5](minimum value is2) has a min-product of2 * (3+2+5) = 2 * 10 = 20.
Given an array of integers nums, return the maximum min-product of any non-empty subarray of nums. Since the answer may be large, return it modulo 109 + 7.
Note that the min-product should be maximized before performing the modulo operation. Testcases are generated such that the maximum min-product without modulo will fit in a 64-bit signed integer.
A subarray is a contiguous part of an array.
Example 1:
Input: nums = [1,2,3,2]
Output: 14
Explanation: The maximum min-product is achieved with the subarray [2,3,2] (minimum value is 2).
2 * (2+3+2) = 2 * 7 = 14.Example 2:
Input: nums = [2,3,3,1,2]
Output: 18
Explanation: The maximum min-product is achieved with the subarray [3,3] (minimum value is 3).
3 * (3+3) = 3 * 6 = 18.Example 3:
Input: nums = [3,1,5,6,4,2]
Output: 60
Explanation: The maximum min-product is achieved with the subarray [5,6,4] (minimum value is 4).
4 * (5+6+4) = 4 * 15 = 60.
Constraints:
1 <= nums.length <= 1051 <= nums[i] <= 107
Approaches
2 approaches with complexity analysis and trade-offs.
This approach considers every possible non-empty subarray. We can iterate through all possible start and end points of a subarray. For each subarray, we calculate its sum and find its minimum element to compute the min-product. A naive implementation would take O(n^3), but we can optimize it to O(n^2).
Algorithm
- Initialize a 64-bit integer
maxProductto 0. - Iterate through the array with an index
ifrom 0 ton-1to select the start of the subarray. - Inside this loop, initialize
currentSum = 0andminVal = Integer.MAX_VALUE. - Start a second loop with an index
jfromiton-1to select the end of the subarray. - In the inner loop, add
nums[j]tocurrentSumand updateminVal = min(minVal, nums[j]). This effectively considers the subarraynums[i...j]. - Calculate the current min-product:
(long)minVal * currentSum. - Update
maxProduct = max(maxProduct, current min-product). - After the loops complete, return
maxProductmodulo 10^9 + 7.
Walkthrough
We use two nested loops. The outer loop fixes the starting index i of the subarray. The inner loop iterates from i to the end of the array, effectively defining the subarray nums[i...j]. For each of these subarrays, we find the minimum value and the sum, calculate the min-product, and update the overall maximum. By updating the sum and minimum incrementally within the inner loop, we achieve an O(n^2) complexity.
class Solution { public int maxSumMinProduct(int[] nums) { int n = nums.length; long maxProduct = 0; final int MOD = 1_000_000_007; for (int i = 0; i < n; i++) { long currentSum = 0; int minVal = Integer.MAX_VALUE; for (int j = i; j < n; j++) { // Extend subarray nums[i...j-1] to nums[i...j] currentSum += nums[j]; minVal = Math.min(minVal, nums[j]); maxProduct = Math.max(maxProduct, minVal * currentSum); } } return (int) (maxProduct % MOD); }}Complexity
Time
O(n^2), where n is the number of elements in `nums`. We have two nested loops iterating through the array.
Space
O(1), as we only use a few variables to store the running sum, minimum, and maximum product.
Trade-offs
Pros
Conceptually simple and easy to implement.
Requires minimal extra space.
Cons
The O(n^2) time complexity is too slow for the given constraints (n <= 10^5) and will result in a 'Time Limit Exceeded' error on most platforms.
Solutions
Solution
class Solution {public int maxSumMinProduct(int[] nums) { int n = nums.length; int[] left = new int[n]; int[] right = new int[n]; Arrays.fill(left, -1); Arrays.fill(right, n); Deque<Integer> stk = new ArrayDeque<>(); for (int i = 0; i < n; ++i) { while (!stk.isEmpty() && nums[stk.peek()] >= nums[i]) { stk.pop(); } if (!stk.isEmpty()) { left[i] = stk.peek(); } stk.push(i); } stk.clear(); for (int i = n - 1; i >= 0; --i) { while (!stk.isEmpty() && nums[stk.peek()] > nums[i]) { stk.pop(); } if (!stk.isEmpty()) { right[i] = stk.peek(); } stk.push(i); } long[] s = new long[n + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + nums[i]; } long ans = 0; for (int i = 0; i < n; ++i) { ans = Math.max(ans, nums[i] * (s[right[i]] - s[left[i] + 1])); } final int mod = (int)1 e9 + 7; return (int)(ans % mod); }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.