Skip to content

Commit 4d88bdb

Browse files
authored
Merge pull request #76 from AbdulWahab938/feature/max-product-subarray
Solution #152 - Abdul Wahab - 17/07/2025
2 parents bc94f21 + 6beb2b9 commit 4d88bdb

File tree

4 files changed

+210
-0
lines changed

4 files changed

+210
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# 152. Maximum Product Subarray
2+
3+
**Difficulty:** Medium
4+
**Category:** Arrays, Dynamic Programming
5+
**Leetcode Link:** [Problem Link](https://leetcode.com/problems/maximum-product-subarray/)
6+
7+
---
8+
9+
## 📝 Introduction
10+
11+
Given an integer array `nums`, find a contiguous non-empty subarray within the array that has the largest product, and return the product.
12+
13+
The problem requires handling negative numbers and zeros, which can disrupt the product and reset subarrays. A subarray must be contiguous, and the result must be the largest product among all possible subarrays.
14+
15+
Constraints:
16+
- 1 <= nums.length <= 2 * 10⁴
17+
- -10 ≤ nums[i] ≤ 10
18+
- The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.
19+
20+
---
21+
22+
## 💡 Approach & Key Insights
23+
24+
To solve this problem, we evaluate various approaches:
25+
26+
- Brute-force: Try all subarrays and compute their products.
27+
- Optimized: Observe properties of negative numbers and zeros.
28+
- Best: Use a modified version of Kadane’s algorithm that tracks both max and min products to handle sign flips.
29+
30+
Key observations:
31+
- Positive product → Keep multiplying.
32+
- Negative product → Might become maximum when multiplied with another negative.
33+
- Zeros → Break the subarray and reset.
34+
35+
---
36+
37+
## 🛠️ Breakdown of Approaches
38+
39+
### 1️⃣ Brute Force / Naive Approach
40+
41+
- **Explanation:**
42+
Generate all possible subarrays using two nested loops. For each subarray, calculate the product of its elements. Keep track of the maximum product seen so far.
43+
44+
- **Time Complexity:** O(N²) - N starting points and N subarray lengths
45+
- **Space Complexity:** O(1) - No extra space used beyond variables
46+
47+
- **Example/Dry Run:**
48+
49+
Example input: [2, 3, -2, 4]
50+
Subarrays:
51+
- [2] → 2
52+
- [2, 3] → 6
53+
- [2, 3, -2] → -12
54+
- [3, -2] → -6
55+
- [-2, 4] → -8
56+
Max = 6
57+
58+
---
59+
60+
### 2️⃣ Optimized Approach
61+
62+
- **Explanation:**
63+
Based on the number of negative elements:
64+
- If all positives → result is the product of entire array.
65+
- If even number of negatives → product of entire array is positive.
66+
- If odd number of negatives → remove one negative (either from start or end) to make the product positive.
67+
68+
Handle 0s by splitting the array into subarrays and applying the above logic on each.
69+
70+
- **Algorithm:**
71+
- Loop through the array, tracking prefix and suffix products.
72+
- Reset the prefix/suffix product to 1 when hitting zero.
73+
- Track the maximum of all such segment products.
74+
75+
- **Time Complexity:** O(N) - Single pass
76+
- **Space Complexity:** O(1) - Only scalar variables used
77+
78+
- **Example/Dry Run:**
79+
80+
Input: [-2, 3, 4, -1, 0, -2, 3, 1, 4, 0, 4, 6, -1, 4]
81+
Break on zeros → {[−2,3,4,−1], [−2,3,1,4], [4,6,−1,4]}
82+
Apply logic on each subarray
83+
Answer = max of all segment max products
84+
85+
---
86+
87+
### 3️⃣ Best / Final Optimized Approach (Kadane-style)
88+
89+
- **Explanation:**
90+
Track the maximum and minimum product ending at the current index. Negative numbers can flip max to min and vice versa. This ensures handling of alternating signs.
91+
92+
- **Algorithm:**
93+
- Initialize prod1 = prod2 = result = nums[0]
94+
- Traverse the array from index 1:
95+
- temp = max(current, current × prod1, current × prod2)
96+
- prod2 = min(current, current × prod1, current × prod2)
97+
- prod1 = temp
98+
- result = max(result, prod1)
99+
100+
- **Time Complexity:** O(N) - Single loop
101+
- **Space Complexity:** O(1) - Constant number of variables
102+
103+
- **Example/Dry Run:**
104+
105+
Input: [1, 2, -3, 0, -4, -5]
106+
Step 1: prod1 = prod2 = result = 1
107+
i = 1: nums[i] = 2 → temp = max(2, 2×1, 2×1) = 2
108+
→ prod1 = 2, prod2 = 2, result = 2
109+
i = 2: nums[i] = -3 → temp = max(-3, -6, -6) = -3
110+
→ prod1 = -3, prod2 = -6, result = 2
111+
i = 3: nums[i] = 0 → temp = 0 → reset
112+
i = 4: nums[i] = -4 → etc.
113+
Final result: 20
114+
115+
---
116+
117+
## 📊 Complexity Analysis
118+
119+
| Approach | Time Complexity | Space Complexity |
120+
| ------------- | --------------- | ---------------- |
121+
| Brute Force | O(N²) | O(1) |
122+
| Optimized | O(N) | O(1) |
123+
| Best Approach | O(N) | O(1) |
124+
125+
---
126+
127+
## 📉 Optimization Ideas
128+
129+
- Use rolling variables instead of arrays to track max/min products.
130+
- Restart subarray product after encountering 0 to ensure correct segmentation.
131+
- Can further optimize by using prefix/suffix scans with early exits.
132+
133+
---
134+
135+
## 📌 Example Walkthroughs & Dry Runs
136+
137+
plaintext
138+
Example:
139+
Input: [2, 3, -2, 4]
140+
Process:
141+
→ 2 → max = 2
142+
→ 2×3 = 6 → max = 6
143+
→ 6×(-2) = -12 → becomes min
144+
→ restart with 4 → max = 6
145+
Output: 6
146+
147+
Another:
148+
Input: [1, 2, -3, 0, -4, -5]
149+
→ Subarray after 0 = [-4, -5] → product = 20
150+
Output: 20
151+
152+
---
153+
154+
## 🔗 Additional Resources
155+
156+
- [Kadane’s Algorithm for Maximum Sum](https://en.wikipedia.org/wiki/Maximum_subarray_problem)
157+
158+
---
159+
160+
Author: Abdul Wahab
161+
Date: 19/07/2025
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class Solution {
2+
public:
3+
int maxProduct(vector<int>& nums) {
4+
int prod1 = nums[0]; // max product ending here
5+
int prod2 = nums[0]; // min product ending here
6+
int result = nums[0];
7+
8+
for (int i = 1; i < nums.size(); i++) {
9+
int temp = max({nums[i], prod1 * nums[i], prod2 * nums[i]});
10+
prod2 = min({nums[i], prod1 * nums[i], prod2 * nums[i]});
11+
prod1 = temp;
12+
13+
result = max(result, prod1);
14+
}
15+
16+
return result;
17+
}
18+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Solution {
2+
public int maxProduct(int[] nums) {
3+
int prod1 = nums[0]; // max product ending here
4+
int prod2 = nums[0]; // min product ending here
5+
int result = nums[0];
6+
7+
for (int i = 1; i < nums.length; i++) {
8+
int temp = Math.max(nums[i], Math.max(prod1 * nums[i], prod2 * nums[i]));
9+
prod2 = Math.min(nums[i], Math.min(prod1 * nums[i], prod2 * nums[i]));
10+
prod1 = temp;
11+
12+
result = Math.max(result, prod1);
13+
}
14+
15+
return result;
16+
}
17+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class Solution:
2+
def maxProduct(self, nums: List[int]) -> int:
3+
prod1 = nums[0] # max product ending here
4+
prod2 = nums[0] # min product ending here
5+
result = nums[0]
6+
7+
for i in range(1, len(nums)):
8+
temp = max(nums[i], prod1 * nums[i], prod2 * nums[i])
9+
prod2 = min(nums[i], prod1 * nums[i], prod2 * nums[i])
10+
prod1 = temp
11+
12+
result = max(result, prod1)
13+
14+
return result

0 commit comments

Comments
 (0)