Minimum Product of a Subset is a clean little greedy problem. You may pick any subset of the array, and you want the product of the picked elements to be as small as possible. The trick is realizing you almost always want to take everything — the only question is how the signs line up.
Problem. Given an array of integers nums, choose a non-empty subset whose product is the
smallest possible, and return that product.
Example: nums = [-1, -1, -2, 4, 3] → answer -24 (multiply every element: -1 × -1 × -2 × 4 × 3 = -24).
The slow way first
The brute-force idea: enumerate every subset, compute each product, and keep the minimum. There are 2^n subsets, so this is O(2ⁿ) — hopeless past a dozen elements.
But look closer. Each element only ever multiplies the product. A positive factor > 1 makes a positive product bigger and a negative product smaller — both move us away from zero, which is what we want. So we essentially never want to leave out a useful element. The whole problem collapses to a sign argument.
The idea: take everything, then fix the sign
Multiply all the non-zero elements together. Now reason about the result:
- Each negative factor flips the sign. With an odd number of negatives the product is already negative — the best possible direction.
- With an even number of negatives the product comes out positive, which is bad. To flip it negative we drop exactly one negative — the largest one (closest to zero, like
-1) — because removing it changes the product the least while flipping the sign.
Zeros are special: a zero would force the product to 0. We skip them, unless the array is all non-positive in a way that makes 0 the best we can do.
The key insight: we want the most negative product, so an odd negative count is already a win, and an even count costs us one division by the closest-to-zero negative.
Walk through it
Step through the animation. The pointer x scans the array. Negatives are counted and max_neg tracks the one closest to zero. With [-1, -1, -2, 4, 3] the running product reaches -24 and the negative count is 3 — odd — so we keep the full product as the answer.
Pseudocode
product = 1
negatives = 0
max_neg = -infinity # largest (closest to zero) negative
for each x in nums:
if x == 0: skip it
if x < 0:
negatives += 1
max_neg = max(max_neg, x)
product *= x
if negatives is even and negatives > 0:
product = product / max_neg # drop one negative to flip the sign
return productThe Python solution
def min_product_subset(nums):
product = 1
negatives = 0
max_neg = float("-inf")
zeros = 0
for x in nums:
if x == 0:
zeros += 1
continue
if x < 0:
negatives += 1
max_neg = max(max_neg, x)
product *= x
if negatives % 2 == 0 and negatives > 0:
product //= max_neg
return product- We multiply only non-zero elements into
product, skipping any zero withcontinue. negativescounts the negative factors andmax_negkeeps the one closest to zero (amaxover negatives).- After the loop, an odd negative count means
productis already negative — we return it as is. - Line 14 catches the even case (positive product); line 15 divides out
max_neg, removing one negative so the sign flips while losing the least magnitude. - The
negatives > 0guard avoids dividing when there were no negatives at all.
Complexity
| Case | Time | Notes |
|---|---|---|
| Brute force (all subsets) | O(2ⁿ) (moderate) | every subset, every product |
| Greedy (this solution) | O(n) (moderate) | one pass, sign bookkeeping |
O(1) (fast)We replace exponential subset enumeration with a single linear scan and a constant amount of bookkeeping — a huge win, and the space is O(1).
When this pattern shows up
When a problem asks for an extreme product or sum over a chosen subset, ask whether each element always helps. If it does, the answer is take-everything, and the only work left is a sign or parity argument — count the negatives, handle zeros, and fix the result.
Watch the edge cases: an array with a single element returns that element; zeros must be skipped (never multiplied in); and when the negative count is even you divide by the negative closest to zero, not the smallest — dividing by the smallest would throw away too much magnitude.
Practice
For nums = [-1, -1, -2, 4, 3], the product of all elements is -24 and there are 3 negatives. Do we keep -24 or fix the sign?
1. Why is the greedy solution O(n) instead of O(2ⁿ)?
2. When the count of negatives is even, which negative do we divide out?
3. How are zeros handled?
4. If the array has exactly one negative and several positives, what is the product's sign?