DSAPrep
EasyArrays & HashingMath & Geometry

Maximum Product of Three Numbers

You are given an integer array nums.

Find three numbers whose product is maximum and return the maximum product.

Example 1

            Input: nums = [1,2,3]
            Output: 6
            

            
                Explanation: The only three numbers are 1, 2, and 3, so the maximum product is 1 * 2 * 3 = 6.
              
          

Example 2

            Input: nums = [1,2,3,4]
            Output: 24
            

            
                Explanation: The largest product comes from the three greatest numbers: 2 * 3 * 4 = 24.
              
          

Example 3

            Input: nums = [-1,-2,-3]
            Output: -6
            

            
                Explanation: The only three numbers are -1, -2, and -3, so the maximum product is (-1) * (-2) * (-3) = -6.
              
          

Constraints

  • 3 <= nums.length <= 10^4
  • -1000 <= nums[i] <= 1000
View original on LeetCode ↗

The pattern insight here is candidate analysis: with negatives in the array, the maximum product is not automatically the three largest values. A negative flips the sign of a product, so two very negative numbers multiply into a huge positive and can out-multiply the second- and third-largest values the moment the array has a single positive anchor. The trick is to sort once, notice that any maximal triple must live at the two ends, and compare exactly two candidates: the three largest values, and the largest value times the two most-negative values. Every middle value loses to both.

Brute Force: Try Every Triple

Time O(n³)Space O(1)

The most literal reading is to try every unordered triple of indices and track the biggest product. Use nested loops with i < j < k so each combination of three distinct elements is checked exactly once, and keep a running maximum. It always returns the right answer because it exhausts every possible choice of three values — but it recomputes the same work over and over with no structure.

class Solution:
def maximumProduct(self, nums: list[int]) -> int:
n = len(nums)
best = -10**18 # smaller than any possible product here
for i in range(n):
for j in range(i + 1, n):
for k in range(j + 1, n):
best = max(best, nums[i] * nums[j] * nums[k])
return best

Why it is cubic: there are about n choose 3 triples, which grows like n³ / 6. For each triple we do a couple of multiplications, so the work is O(n³). On .length = 10^4 that means roughly 1.6 × 10^11 triples — far too many. It is correct but useless at scale, and it ignores the structure that makes the problem easy.

Sort + Two Candidates

OptimalTime O(n log n)Space O(1)

Sort ascending, then the two ends carry everything the answer needs. Candidate A is the product of the three largest values (the last three in the sorted array). Candidate B is the product of the largest value and the two most-negative values (the first two) — because negative × negative is positive, so the two smallest values are secretly the two largest magnitudes, and paired with the largest value they can dwarf candidate A. The answer is simply max(A, B).

class Solution:
def maximumProduct(self, nums: list[int]) -> int:
nums.sort()
n = len(nums)
# Candidate A: the three largest values.
largest_three = nums[-1] * nums[-2] * nums[-3]
# Candidate B: the largest value times the two most negative.
largest_with_negatives = nums[-1] * nums[0] * nums[1]
return max(largest_three, largest_with_negatives)

Watch the file example, [-100, -98, -1, 2, 3, 4], where the two most-negative values blow past the three largest — candidate B wins at 39200:

start · find the largest product of any three

input — unsorted

-100-98-1234

sorted — the answer comes from the ends

the ascending sort runs first — then only the two ends matter

candidate A · three largest

432=24

candidate B · largest × two most negative

4-100-98=39200

two negatives multiplied make a positive — so the two most-negative values can hand the largest value a far bigger partner than the second- and third-largest ever could

1 / 7
comparingresultseen

The trap in this problem: the maximum product is NOT always the three biggest values. A negative times a negative flips back to positive, so an array with a couple of very negative numbers can beat the three largest if the negatives are big enough. Sort the array first — sorting pulls the two extremes to the two ends, and the answer is always built from those ends, never from the sorted middle.

Then the all-negative case, [-1, -2, -3], where only three numbers exist so both candidates converge on the whole array:

start · all-negative input [-1,-2,-3]

input — unsorted

-1-2-3

sorted — the answer comes from the ends

the ascending sort runs first — then only the two ends matter

candidate A · three largest

-1-2-3=-6

candidate B · largest × two most negative

-1-3-2=-6

two negatives multiplied make a positive — so the two most-negative values can hand the largest value a far bigger partner than the second- and third-largest ever could

1 / 4
comparingresultseen

Now every value is negative. With negatives the largest (least negative) value is the multiplicative anchor, so the best product comes from anchoring at -1 (the largest) and pairing with the two smallest: -1 · -2 · -3. With only three numbers the answer is simply their product, -6.

Why both candidates are necessary: with all-positive numbers candidate A trivially wins and the problem collapses to the three largest. But with a pair of strong negatives, candidate B wins — as in [-100,-98,-1,2,3,4], where 4 · (-100) · (-98) = 39200 beats 4 · 3 · 2 = 24 by far. A sorted middle value like -1 can never help, because swapping it for its larger right neighbor or its more-negative left neighbor never shrinks the product. So evaluating both candidates and taking the max, the formula stays correct for positive-only, negative-only, and mixed arrays alike.

Why it is optimal for this approach: one sort costs O(n log n) and produces the two ends directly; the two products and the max are O(1), and we reuse the input array so space is O(1) (ignoring the sort’s internal recursion stack). You cannot answer the question without examining every element, and O(n log n) easily clears 10^4.

The O(n) variant: because only the two smallest and three largest values matter, you can skip the sort entirely and track five variables in one pass — mi1, mi2 for the two smallest, mx1, mx2, mx3 for the three largest — then take max(mi1 * mi2 * mx1, mx1 * mx2 * mx3). That is O(n) time and O(1) space, and it is the version you would recite in an interview to drop the log factor.

from math import inf
class Solution:
def maximumProduct(self, nums: list[int]) -> int:
mi1 = mi2 = inf
mx1 = mx2 = mx3 = -inf
for x in nums:
if x < mi1:
mi2, mi1 = mi1, x
elif x < mi2:
mi2 = x
if x > mx1:
mx3, mx2, mx1 = mx2, mx1, x
elif x > mx2:
mx3, mx2 = mx2, x
elif x > mx3:
mx3 = x
return max(mi1 * mi2 * mx1, mx1 * mx2 * mx3)