—
curMax
Unlike sum, a product can explode positive via two negatives — so you must track both the running maximum and minimum product ending at each index, because a negative number turns the worst product into the best.
Given an integer array nums, return the largest product of any contiguous subarray. For [2, 3, -2, 4] the answer is 6 (subarray [2, 3]). For [-2, 0, -1] the answer is 0 because the zero isolates both negatives and no subarray of just [-2, -1] is contiguous.
curMax, curMin, and best all to nums[0]. Handles the single-element edge case automatically.nums[i], compute three candidates: nums[i] alone (start a fresh subarray), curMax * nums[i], and curMin * nums[i].curMax = the largest of the three; new curMin = the smallest. Use a temp variable — both updates must read the old curMax/curMin.best = Math.max(best, curMax). Only the max can beat the running answer.curMax = Math.max(..., curMax*n, curMin*n) and then curMin = Math.min(..., curMax*n, ...), the second line reads the already-updated curMax — producing a subtly wrong answer. Always compute tmpMax and tmpMin from the same old values, then assign both.An alternative is to keep running left-to-right prefix products and right-to-left prefix products, taking the max over all positions. It works because a zero "resets" the window from both sides. The min/max approach above is more intuitive and slightly simpler to explain.
[2, 3, -2, 4]. We track both the running max and min product ending here — a negative number can flip the min into a new max.function maxProduct(nums: number[]): number {
let curMax = nums[0];
let curMin = nums[0];
let best = nums[0];
for (let i = 1; i < nums.length; i++) {
const n = nums[i];
// A negative n flips curMin into the new curMax — compute all three candidates.
const tmpMax = Math.max(n, curMax * n, curMin * n);
const tmpMin = Math.min(n, curMax * n, curMin * n);
curMax = tmpMax;
curMin = tmpMin;
best = Math.max(best, curMax);
}
return best;
}nums[0] handles single-element arrays (the answer is just that element) and gives a valid base for the loop that follows.n alone), extends the previous maximum (curMax * n), or extends the previous minimum (curMin * n) — which is crucial when n is negative. Storing in tmpMax / tmpMin before assignment prevents a data-hazard where the updated curMax contaminates the curMin computation.curMax can beat the global record; curMin is kept only to seed the next iteration.curMax; when curMax resets to n alone, record the new start. Keep a separate best-start/best-end pair updated whenever best improves.curMax and curMinto 0, then the next element seeds a fresh window via the "n alone" candidate. The algorithm handles zeros automatically — no special case needed.best tracking curMin instead — symmetric by replacing every max with min and vice versa.| "maximum product of a subarray" | Kadane + min/max dual tracker |
| subarray with negative numbers involved in product | carry curMin alongside curMax |
| Kadane breaks because of sign flips | add the opposite extreme tracker |
| "contiguous subarray, multiply not add" | seed curMax=curMin=nums[0], three candidates |
let curMax = nums[0];
let curMin = nums[0];
let best = nums[0];
for (let i = 1; i < nums.length; i++) {
const n = nums[i];
const tmpMax = Math.max(n, curMax * n, curMin * n);
const tmpMin = Math.min(n, curMax * n, curMin * n);
curMax = tmpMax;
curMin = tmpMin;
best = Math.max(best, curMax);
}
return best;