Maximum Product Subarray
Max product of any contiguous subarray — track current max AND current min (negatives flip).
3 min read
dp array
Problem#
Return the largest product of any contiguous non-empty subarray.
Examples#
[2,3,-2,4]→6([2,3])[-2,0,-1]→0
Constraints#
1 <= n <= 2 * 10^4.
Approach#
Track two running values: curMax and curMin ending at the current index. On a negative, they swap roles. Update best from curMax.
Solution#
class Solution {public: int maxProduct(vector<int>& nums) { int curMax = nums[0], curMin = nums[0], best = nums[0]; for (int i = 1; i < (int)nums.size(); ++i) { int x = nums[i]; if (x < 0) swap(curMax, curMin); curMax = max(x, curMax * x); curMin = min(x, curMin * x); best = max(best, curMax); } return best; }};func maxProduct(nums []int) int { curMax, curMin, best := nums[0], nums[0], nums[0] for i := 1; i < len(nums); i++ { x := nums[i] if x < 0 { curMax, curMin = curMin, curMax } if x > curMax*x { curMax = x } else { curMax = curMax * x } if x < curMin*x { curMin = x } else { curMin = curMin * x } if curMax > best { best = curMax } } return best}from typing import List
class Solution: def maxProduct(self, nums: List[int]) -> int: cur_max = cur_min = best = nums[0] for x in nums[1:]: if x < 0: cur_max, cur_min = cur_min, cur_max cur_max = max(x, cur_max * x) cur_min = min(x, cur_min * x) best = max(best, cur_max) return bestfunction maxProduct(nums) { let curMax = nums[0], curMin = nums[0], best = nums[0]; for (let i = 1; i < nums.length; i++) { const x = nums[i]; if (x < 0) [curMax, curMin] = [curMin, curMax]; curMax = Math.max(x, curMax * x); curMin = Math.min(x, curMin * x); best = Math.max(best, curMax); } return best;}class Solution { public int maxProduct(int[] nums) { int curMax = nums[0], curMin = nums[0], best = nums[0]; for (int i = 1; i < nums.length; i++) { int x = nums[i]; if (x < 0) { int tmp = curMax; curMax = curMin; curMin = tmp; } curMax = Math.max(x, curMax * x); curMin = Math.min(x, curMin * x); best = Math.max(best, curMax); } return best; }}function maxProduct(nums: number[]): number { let curMax = nums[0], curMin = nums[0], best = nums[0]; for (let i = 1; i < nums.length; i++) { const x = nums[i]; if (x < 0) [curMax, curMin] = [curMin, curMax]; curMax = Math.max(x, curMax * x); curMin = Math.min(x, curMin * x); best = Math.max(best, curMax); } return best;}Editorial#
Negatives invalidate the “running max only” idea (a big negative × small negative may produce the new max). Tracking both extremes covers all cases: swapping on a negative repositions them for the multiplication.
Complexity#
- Time: O(n).
- Space: O(1).
Concept revision#
Related#