150NeetCode 150

107.Maximum Product Subarray

MediumBlind 751-D Dynamic Programming · 9/12

Problem

Given an integer array nums, find the contiguous, non-empty subarray whose elements have the largest product, and return that product.

The values can be negative or zero, and the answer is guaranteed to fit in a 32-bit integer.

Examples

Input:  nums = [2, 3, -2, 4]
Output: 6
Explanation: The subarray [2, 3] has product 6.
Input:  nums = [-2, 0, -1]
Output: 0
Explanation: [-2, -1] is not contiguous, so the best is [0].
Input:  nums = [-2, 3, -4]
Output: 24
Explanation: The whole array: two negatives make a positive.

Constraints

  • 1 <= nums.length <= 2 * 10^4
  • -10 <= nums[i] <= 10
  • The product of any subarray fits in a 32-bit integer.

💡 Key Insight

With sums (Kadane), the best subarray ending at i only needs the best ending at i - 1. With products, a negative number flips the order: the smallest (most negative) product ending at i - 1, multiplied by a negative nums[i], may become the largest. So track both: maxEnd(i) = max(nums[i], nums[i]·maxEnd(i-1), nums[i]·minEnd(i-1)) and minEnd(i) = min(nums[i], nums[i]·maxEnd(i-1), nums[i]·minEnd(i-1)). The nums[i] option alone lets a zero "reset" the run. The answer is the max of maxEnd(i) over all i, and only the previous pair is needed — O(n) time, O(1) space.

Brute Force

TimeO(n²)SpaceO(1).

Intuition

Try every start i, extend the end j one step at a time while maintaining the running product, and keep the best product seen.

Algorithm

  1. best = nums[0].
  2. For each i: prod = 1; for j = i..n-1: prod *= nums[j], best = max(best, prod).
  3. Return best.

Visualization

nums = [2, 3, -2, 4]
i=0: 2, 6, -12, -48     best so far 6
i=1: 3, -6, -24         best 6
i=2: -2, -8             best 6
i=3: 4                  best 6

Code

java
class Solution {
    public int maxProduct(int[] nums) {
        int best = nums[0];
        for (int i = 0; i < nums.length; i++) {
            int prod = 1;
            for (int j = i; j < nums.length; j++) {
                prod *= nums[j]; // product of nums[i..j]
                best = Math.max(best, prod);
            }
        }
        return best;
    }
}

Complexity

  • Time: O(n²) — every subarray, with O(1) incremental product.
  • Space: O(1).

Complexity Comparison

Approach Time Space
Brute Force O(n²) O(1)
Top-Down Memoization O(n) O(n)
Bottom-Up Tabulation O(n) O(n)
Space-Optimized DP O(n) O(1)

Common Pitfalls

  • Tracking only the maximum — [-2, 3, -4] needs the stored minimum -6 to reach 24.
  • Updating curMax first and then using the new curMax to compute curMin; save the old values (or the products) first.
  • Initialising best = 0 — an all-negative single element like [-3] must return -3.
  • Forgetting the "start fresh at nums[i]" option, which is what lets a 0 break the run.