The O(n) Club: Maximum Product of Three Numbers — Beware the Negative Numbers Plot Twist
⚡ TL;DR
Want the biggest product from any three numbers in an array? Instinct says “pick the top three.” But if you gloss over negatives, you’re basically setting your code up for cartoon physics. Sometimes, the optimal product involves two massive negatives and one gigantic positive. Brute-force means baking your CPU with O(n³) — but with some math judo, you can solve it in a single pass.
// Brute force (please don't): int max = Integer.MIN_VALUE; for (int i = 0; i < nums.length; i++) for (int j = i+1; j < nums.length; j++) for (int k = j+1; k < nums.length; k++) max = Math.max(max, nums[i]*nums[j]*nums[k]);
🧠 How Devs Usually Mess This Up
Most devs think, “I’ll just sort and grab the top three — rapid success!” Except when two negatives decide to join the hackathon and multiply, they flip the sign and hijack your max. If your code’s only hunting for the biggest values, those unexpected negatives will tap-dance all over your output. And if you’re still sitting in O(n³), please — your computer wants to retire, not overheat.
- Neglecting negatives: Ignoring how -20 × -19 × 1 > 10 × 9 × 8. Oops.
- Testing every combo: Brute force is for the gym, not production code.
- Forgetting all-negative or zero-filled arrays: Precarious edge cases lurk!
🔍 What’s Actually Going On
Picture a chef: to make the most potent sauce, you need the highest-impact ingredients, which could mean the hottest chilies or the sourest lemons. Here, “flavor” = “magnitude.” The best combo might be three super positives, or it might be “two negatives plus one positive” because negatives multiplied together turn… positive (math’s plot twist of the century). If you miss the possibility of a negative-negative-positive triple, you’ll serve bland code and flunk the taste test.
🛠️ PseudoCode
- Initialize variables for the top 3 largest and 2 smallest numbers.
- Loop through the array:
- Update max1, max2, max3 if you find a new largest.
- Update min1, min2 if you find a new smallest (most negative).
- Two competitor products:
- Product A: max1 × max2 × max3
- Product B: min1 × min2 × max1 (the sneaky negative double-cross)
- Return the bigger product.
// Java snippet logic
for (int num : nums) {
// find max1, max2, max3
// find min1, min2
}
int prod1 = max1 * max2 * max3;
int prod2 = max1 * min1 * min2;
return Math.max(prod1, prod2);
💻 The Code
public int maximumProduct(int[] nums) {
int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE;
int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
for (int n : nums) {
// Find the three largest numbers
if (n > max1) {
max3 = max2;
max2 = max1;
max1 = n;
} else if (n > max2) {
max3 = max2;
max2 = n;
} else if (n > max3) {
max3 = n;
}
// Find the two smallest numbers
if (n < min1) {
min2 = min1;
min1 = n;
} else if (n < min2) {
min2 = n;
}
}
return Math.max(max1 * max2 * max3, max1 * min1 * min2);
}
⚠️ Pitfalls, Traps & Runtime Smacks
- All elements negative? Pick the three closest to zero (aka “least bad” combination).
- Zeros dilute greatness — don’t let a zero sneak in unless you’re desperate for a non-negative result.
- Integer overflow: Java won’t break, but your result definitely will for giant numbers.
- Turns out, O(n) time, O(1) space feels as good as inbox zero.
🧠 Interviewer Brain-Tattoo
“If your max product is flat, check your negatives — the only time in tech when two problems really do make a positive.”