Last Updated: March 22, 2026
We need to find a contiguous subarray within nums whose elements multiply together to give the largest possible product.
This problem looks a lot like Maximum Subarray (Kadane's algorithm), but there's a twist that makes it trickier: negative numbers. With sums, a negative number is always bad. With products, a negative number can become your best friend if it meets another negative number down the road. The product of two negatives is positive, so the smallest (most negative) product so far could suddenly become the largest product after one multiplication.
Zeros add another wrinkle. Any subarray containing a zero has a product of zero, which effectively resets everything. So the problem breaks down into reasoning about three things: positive numbers that grow the product, negative numbers that flip the sign, and zeros that kill the product entirely.
nums.length <= 2 * 10^4 → An O(n^2) solution should pass comfortably, and O(n) is ideal-10 <= nums[i] <= 10 → Values are small, so individual multiplications won't overflow, but subarray products can grow (the problem guarantees they fit in a 32-bit integer)The most straightforward approach is to check every possible subarray, compute its product, and keep track of the largest one. For each starting index i, we extend the subarray to the right one element at a time, multiplying as we go. This gives us the product of every subarray without recalculating from scratch each time.
maxProduct to the first element of the array (handles the single-element case).i from 0 to n-1:currentProduct = 1.j from i to n-1:currentProduct by nums[j].maxProduct if currentProduct is larger.maxProduct.n times, and for each iteration, the inner loop runs up to n times. Each inner iteration does O(1) work (one multiplication and one comparison).For each starting index, we scan forward through the rest of the array to compute every subarray product. What if we could process each element just once, keeping track of enough information at each position to determine the maximum product ending there?
If this were Maximum Subarray Sum, we'd use Kadane's algorithm: at each position, the maximum sum ending here is either the current element alone or the current element plus the previous maximum sum. Simple.
But products behave differently. A large negative product times a negative number becomes a large positive product. So the minimum product at the previous position matters just as much as the maximum. Here's the key insight: at each position, track both the maximum and minimum product ending there.
At each element nums[i], the maximum product ending at position i is the largest of three candidates:
nums[i] alone (start a fresh subarray)maxSoFar * nums[i] (extend the previous best)minSoFar * nums[i] (a negative times a negative might be the new best)The minimum product ending at position i follows the same logic but takes the smallest of the three. We need the minimum because it might become the maximum at the next step if we hit another negative number.
With addition, a negative running sum is always bad. With multiplication, a negative running product can become your best friend. If you have a running product of -12 and the next element is -3, you get 36. That's why standard Kadane's doesn't work here. You need to remember the most negative product so it can flip to the most positive when it meets another negative.
Zeros are handled naturally: when nums[i] = 0, all three candidates (0, maxSoFar * 0, minSoFar * 0) are 0, so both maxSoFar and minSoFar reset to 0. This effectively starts a new subarray at the next element.
maxSoFar, minSoFar, and result to nums[0].1:tempMax = max(nums[i], maxSoFar * nums[i], minSoFar * nums[i]).tempMin = min(nums[i], maxSoFar * nums[i], minSoFar * nums[i]).maxSoFar = tempMax and minSoFar = tempMin.result = max(result, maxSoFar).result.Note: We compute both tempMax and tempMin before updating either one, because updating maxSoFar first would corrupt the calculation of minSoFar.
maxSoFar, minSoFar, result, and temporaries).This approach is optimal in time, but there's an alternative O(n) approach that uses a different insight and can be easier to reason about in interviews. What if we just computed products from both ends of the array and took the maximum?
Here's a completely different way to think about it. Consider the array without any zeros. If the array has an even number of negative numbers, the answer is the product of the entire array (all negatives cancel out). If it has an odd number of negatives, the answer is the larger of two options: drop the leftmost negative and everything before it, or drop the rightmost negative and everything after it.
This leads to a clean approach: compute prefix products (left to right) and suffix products (right to left), and the answer is the maximum across all of them. When we hit a zero, we reset the running product to 1, because zero splits the array into independent segments.
Why does this work? The maximum product subarray must start from the left end of some segment or end at the right end of some segment (where segments are separated by zeros). The prefix pass catches subarrays anchored to the left, and the suffix pass catches subarrays anchored to the right. Between the two passes, we cover every optimal subarray.
result to the first element, prefix = 0, and suffix = 0.prefix is 0, reset it to 1 (start a new segment).prefix by nums[i].suffix is 0, reset it to 1.suffix by nums[n - 1 - i] (building the product from the right).result = max(result, prefix, suffix).result.