max product
consecutive elements
array computation
algorithm optimization
programming techniques

The max product of consecutive elements in an array

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

The maximum product of consecutive elements problem asks for the contiguous part of an array whose product is largest. It looks similar to the better-known maximum sum subarray problem, but multiplication behaves very differently because negative values can suddenly turn a bad partial result into the best one.

Why Products Are Tricky

If the array contained only positive numbers, the problem would be simple: extending a good subarray would keep improving the product. Real inputs are harder because of two cases:

  • A zero resets the running product.
  • A negative number flips the sign, so the smallest product so far may become the largest after multiplication.

That second point is the key insight. You cannot track only the current maximum product. You also need the current minimum product, because a large negative magnitude can become a large positive value after the next negative number appears.

Consider the array [-2, 3, -4].

  • After -2, the best product ending here is -2.
  • After 3, the best ending here is 3, while the worst is -6.
  • After -4, the previous worst product -6 becomes 24, which is now the best answer.

Without storing both extremes, you miss the optimal subarray.

An Efficient Dynamic Programming Approach

The standard linear-time solution keeps three values while scanning left to right:

  • 'max_ending_here'
  • 'min_ending_here'
  • 'best'

When the current number is negative, the roles of the max and min values swap. Then you update both using either the current number alone or the current number multiplied by the previous running value.

python
1def max_product_subarray(nums):
2    if not nums:
3        raise ValueError("nums must not be empty")
4
5    max_ending_here = nums[0]
6    min_ending_here = nums[0]
7    best = nums[0]
8
9    for value in nums[1:]:
10        if value < 0:
11            max_ending_here, min_ending_here = min_ending_here, max_ending_here
12
13        max_ending_here = max(value, max_ending_here * value)
14        min_ending_here = min(value, min_ending_here * value)
15        best = max(best, max_ending_here)
16
17    return best
18
19
20print(max_product_subarray([2, 3, -2, 4]))      # 6
21print(max_product_subarray([-2, 0, -1]))        # 0
22print(max_product_subarray([-2, 3, -4]))        # 24

This runs in O(n) time and O(1) extra space, which is usually optimal for the problem.

Step-by-Step Intuition

Take the input [2, 3, -2, 4].

Start with:

  • 'max_ending_here = 2'
  • 'min_ending_here = 2'
  • 'best = 2'

At 3:

  • 'max_ending_here = max(3, 2 * 3) = 6'
  • 'min_ending_here = min(3, 2 * 3) = 3'
  • 'best = 6'

At -2, swap first because the sign flips:

  • previous max becomes candidate min
  • previous min becomes candidate max

Then update:

  • 'max_ending_here = max(-2, 3 * -2) = -2'
  • 'min_ending_here = min(-2, 6 * -2) = -12'
  • 'best stays 6'

At 4:

  • 'max_ending_here = max(4, -2 * 4) = 4'
  • 'min_ending_here = min(4, -12 * 4) = -48'
  • 'best stays 6'

The answer is 6, produced by the subarray [2, 3].

What About "At Least Two Elements"?

Some interview variants require the subarray to contain two or more elements. The code above allows a single element to be the answer, which is the most common definition.

If you must enforce length at least two, one practical approach is:

  1. Run the standard algorithm to understand the product behavior.
  2. Track pair starts and lengths explicitly, or
  3. Use a slightly more verbose dynamic programming solution that stores both product and length.

The central idea does not change: you still need both a running maximum and a running minimum because of negative numbers.

Common Pitfalls

The biggest mistake is tracking only the maximum running product. That fails on cases such as [-2, 3, -4], where the best result is created by a previously bad negative product.

Another common bug is mishandling zeros. A zero can be the best answer if every other product is negative, and it also breaks contiguity for any product that crosses it.

People also sometimes confuse "consecutive" with "any subset." This problem is about contiguous subarrays, not arbitrary selections from the array.

Finally, test edge cases carefully:

  • one element
  • all negatives
  • zeros in the middle
  • alternating signs

Those inputs reveal most implementation mistakes quickly.

Summary

  • The problem asks for the largest product from a contiguous subarray.
  • Negative numbers make the minimum running product just as important as the maximum one.
  • The standard solution keeps max_ending_here, min_ending_here, and best.
  • A zero resets the running product and must be handled explicitly.
  • The linear-time dynamic programming approach is the usual correct and efficient solution.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.