Maximum Product Subarray

You are given an integer list nums. A subarray is a non-empty run of consecutive elements.

Return the largest product that the elements of any subarray can have. Values can be negative or zero, so the best subarray is not necessarily the longest one.

The inputs are chosen so that the product of every subarray fits in a signed 32-bit integer.

Example 1

Input: nums = [-2,-3,-1,-4,2] Output: 48 Why: The whole list multiplies to (-2)·(-3)·(-1)·(-4)·(2)... the best run is [-2, -3, ..., 2]: see the full product 48.

Example 2

Input: nums = [-2,0,-1] Output: 0 Why: Any subarray containing 0 has product 0, and -2 alone is worse, so the answer is 0.

Example 3

Input: nums = [-7] Output: -7 Why: A single negative number is the only subarray, so it is the answer.

Constraints

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

Pattern Path · Dynamic Programming · problem 154 of 169

For maximum sum, you only track the best sum ending at each position. Why is that not enough for products?
Multiplying by a negative number turns the smallest product into the largest one. So the most negative product ending here is also worth remembering.
At each element x, the new maximum and minimum products ending here are among x, x · prevMax and x · prevMin.
Target: O(n) time, O(1) extra space.

Start simple

Multiply out every subarray starting at each index: O(n²) time.

The key idea

This is a variation of the classic maximum-subarray scan, with one twist: a negative factor flips the order of products. A very negative product ending at i - 1 becomes a very positive one if nums[i] is negative. So keep two values for each position:

  • hi: the largest product of a subarray ending at the current position,
  • lo: the smallest (most negative) product of a subarray ending there.

A subarray ending at x = nums[i] is either x alone or a subarray ending at i - 1 extended by x. Extending multiplies by x, which is monotone in the old product: increasing if x > 0, decreasing if x < 0. So the extremes of the extended products come from the old extremes, and

hi, lo = max(x, x·hi, x·lo), min(x, x·hi, x·lo)

(computed from the old values simultaneously). Taking x alone also covers restarting after a zero. The answer is the largest hi seen anywhere.

Each step is constant work, giving a single O(n) pass with O(1) memory.

Complexity

  • Time: O(n)
  • Space: O(1)

Python

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        # hi / lo: largest and smallest product of a subarray ending at the current element.
        hi = lo = best = nums[0]
        for x in nums[1:]:
            candidates = (x, x * hi, x * lo)
            hi, lo = max(candidates), min(candidates)
            best = max(best, hi)
        return best

JavaScript

var maxProduct = function(nums) {
  // hi / lo: largest and smallest product of a subarray ending at the current element.
  let hi = nums[0], lo = nums[0], best = nums[0];
  for (let i = 1; i < nums.length; i++) {
    const x = nums[i];
    const a = x * hi, b = x * lo;
    hi = Math.max(x, a, b);
    lo = Math.min(x, a, b);
    best = Math.max(best, hi);
  }
  return best;
};

What the interviewer is checking

The interviewer wants to see whether you adapt Kadane's algorithm thoughtfully, noticing that negatives require tracking the minimum as well as the maximum.

Mistakes to avoid

  • Tracking only the maximum product, which loses answers like [-2, 3, -4] = 24.
  • Updating hi first and then using the new hi to compute lo.
  • Initialising the answer to 0, which is wrong for a list such as [-5].

Follow-ups to expect

  • Return the subarray itself, not just its product? (Track start index on restarts.)
  • What if products could overflow? (Logs of absolute values plus sign counting.)
  • Another approach? (Best of prefix and suffix products, resetting at zeros.)

In real software

Compounded growth rates are products of factors, so finding the best stretch of consecutive returns (where some periods are losses) uses the same min/max tracking.

Practice next

Next Post Previous Post
No Comment
Add Comment
comment url