githubEdit

08. Maximum Product Subarray

βœ… GFG solution to the Maximum Product Subarray problem: find the maximum product of any subarray using dynamic programming technique. πŸš€

The problem can be found at the following link: πŸ”— Question Linkarrow-up-right

🧩 Problem Description

Given an array arr[] that contains positive and negative integers (may contain 0 as well). Find the maximum product that we can get in a subarray of arr[].

A subarray is a contiguous sequence of elements within an array. The goal is to find the maximum possible product of elements in any such subarray.

Note: It is guaranteed that the answer fits in a 32-bit integer.

πŸ“˜ Examples

Example 1

Input: arr[] = [-2, 6, -3, -10, 0, 2]
Output: 180
Explanation: The subarray with maximum product is [6, -3, -10] with product = 6 * (-3) * (-10) = 180.

Example 2

Input: arr[] = [-1, -3, -10, 0, 6]
Output: 30
Explanation: The subarray with maximum product is [-3, -10] with product = (-3) * (-10) = 30.

Example 3

πŸ”’ Constraints

  • $1 \le \text{arr.size()} \le 10^6$

  • $-10 \le \text{arr}[i] \le 10$

βœ… My Approach

The optimal approach uses Dynamic Programming with Max-Min Tracking to efficiently handle both positive and negative numbers:

Max-Min Tracking (Modified Kadane's Algorithm)

  1. Initialize Variables:

    • mx = maximum product ending at current position (initialized to arr[0])

    • mn = minimum product ending at current position (initialized to arr[0])

    • r = global maximum product result (initialized to arr[0])

  2. Key Insight:

    • We need to track both maximum AND minimum products because:

      • A negative number can turn the minimum product into maximum

      • A negative number can turn the maximum product into minimum

    • Example: If mn = -10 and current element is -3, then -10 * -3 = 30 becomes the new maximum

  3. Iterate Through Array:

    • For each element arr[i] (starting from index 1):

      • Calculate a = mx * arr[i] (product with previous max)

      • Calculate b = mn * arr[i] (product with previous min)

      • Update mx = max(a, b, arr[i]) (either extend previous products or start fresh)

      • Update mn = min(a, b, arr[i]) (track minimum for future negative multiplications)

      • Update global result: r = max(r, mx)

  4. Handle Edge Cases:

    • Zero elements: When we encounter 0, both max and min reset to 0, and starting fresh from next element handles it naturally

    • All negatives: The min-max tracking ensures correct handling

    • Mixed signs: The dual tracking captures all possibilities

πŸ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(n), where n is the size of the array. We traverse the array exactly once, performing constant-time operations at each step.

  • Expected Auxiliary Space Complexity: O(1), as we only use three variables (mx, mn, r) regardless of input size, requiring constant additional space.

πŸ§‘β€πŸ’» Code (C)

πŸ§‘β€πŸ’» Code (C++)

chevron-right⚑ View Alternative Approaches with Code and Analysishashtag

πŸ“Š 2️⃣ Two-Pass Traversal

πŸ’‘ Algorithm Steps:

  1. Traverse array left to right maintaining cumulative product.

  2. Reset product to zero when product becomes zero.

  3. Traverse array right to left with the same logic.

  4. Track maximum product found in both directions.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Two linear passes through the array

  • Auxiliary Space: πŸ’Ύ O(1) - Constant space complexity

βœ… Why This Approach?

  • Handles negative numbers naturally with bidirectional scan

  • Simpler logic than tracking min and max simultaneously

  • Auto-resets on encountering zeros

πŸ“Š 3️⃣ Prefix-Suffix Product

πŸ’‘ Algorithm Steps:

  1. Calculate prefix product from left and suffix product from right simultaneously.

  2. Reset prefix or suffix to 1 when encountering zero.

  3. Track maximum value from both prefix and suffix at each step.

  4. Return the maximum product found in single pass.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Single pass with dual direction processing

  • Auxiliary Space: πŸ’Ύ O(1) - Only tracking prefix and suffix

βœ… Why This Approach?

  • Single pass efficiency

  • Symmetric processing from both ends

  • Clean zero handling with reset mechanism

πŸ“Š 4️⃣ Modified Kadane's Algorithm with Swap

πŸ’‘ Algorithm Steps:

  1. Maintain three variables: current max, current min, and global max.

  2. For each element, calculate new max as max of current element, maxelement, minelement.

  3. Calculate new min similarly to handle negative number transitions.

  4. Update global maximum at each step.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Single pass with swap on negatives

  • Auxiliary Space: πŸ’Ύ O(1) - Three variables for tracking

βœ… Why This Approach?

  • Extension of classic Kadane's algorithm

  • Explicit swap logic for negative numbers

  • Clear state transitions

πŸ“Š 5️⃣ Division-Based Approach

πŸ’‘ Algorithm Steps:

  1. Calculate product of all non-zero elements.

  2. Split array by zeros into segments.

  3. For segments with odd negative count, try excluding first or last negative.

  4. Return maximum product across all valid segments.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Two passes for forward and backward

  • Auxiliary Space: πŸ’Ύ O(1) - Constant space usage

βœ… Why This Approach?

  • Handles zeros and negatives effectively

  • Double pass ensures optimal subarray selection

  • Good for arrays with multiple zero partitions

πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time Complexity

πŸ’Ύ Space Complexity

βœ… Pros

⚠️ Cons

🏷️ Max-Min Tracking

🟒 O(n)

🟒 O(1)

πŸš€ Optimal single pass

πŸ”§ Tracks both max and min

πŸ“Š Two-Pass Traversal

🟒 O(n)

🟒 O(1)

🎯 Intuitive bidirectional

πŸ”„ Requires two complete passes

πŸ”„ Prefix-Suffix

🟒 O(n)

🟒 O(1)

⭐ Single pass efficiency

🧠 Simultaneous tracking needed

🎨 Modified Kadane's

🟒 O(n)

🟒 O(1)

πŸ“š Classic algorithm pattern

πŸ”„ Explicit swap on negatives

βž— Division-Based

🟒 O(n)

🟒 O(1)

🎯 Handles zeros naturally

πŸ”§ More complex logic flow

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended Approach

πŸ”₯ Performance Rating

πŸ… Optimal performance needed

πŸ₯‡ Max-Min Tracking

β˜…β˜…β˜…β˜…β˜…

πŸ“– Readability priority

πŸ₯ˆ Two-Pass Traversal

β˜…β˜…β˜…β˜…β˜†

🎯 Interview/Competitive

πŸ₯‰ Prefix-Suffix

β˜…β˜…β˜…β˜…β˜…

πŸ“š Algorithm pattern practice

πŸŽ–οΈ Modified Kadane's

β˜…β˜…β˜…β˜…β˜†

πŸ”’ Many zeros in array

πŸ… Division-Based

β˜…β˜…β˜…β˜…β˜†

β˜• Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: πŸ“¬ Any Questions?arrow-up-right. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated