Product of Array Except Self — LeetCode #238
Product of Array Except Self (LeetCode #238) is one of the most frequently asked medium-difficulty problems across all major tech companies. It consistently ranks in the top 15 most-asked mediums at Amazon, Google, Meta, and Microsoft — and for good reason.
The problem sounds deceptively simple: given an integer array nums, return an array where each element at index i is the product of every element in the array except nums[i]. The catch? You cannot use division, and you must solve it in O(n) time.
This constraint is what makes the problem interesting. Without division, you cannot just compute a total product and divide by each element. You need a fundamentally different approach — and the solution reveals one of the most elegant patterns in array manipulation.
Understanding the Product of Array Except Self Problem
Given nums = [1, 2, 3, 4], the expected output is [24, 12, 8, 6]. At index 0, the product of everything except 1 is 2 * 3 * 4 = 24. At index 1, the product of everything except 2 is 1 * 3 * 4 = 12. And so on.
The brute force approach would be to compute the product for each index by iterating through the entire array (skipping the current element) — giving O(n^2) time. But the problem requires O(n), and explicitly bans division.
Why does the problem ban division? Because division introduces edge cases with zeros and does not test the real skill the interviewer wants to see: your ability to decompose a problem using prefix and suffix computations. This is a pattern you will encounter again and again.
Did You Know
Product of Array Except Self (#238) is a top 15 most-asked Medium across all FAANG companies — it tests your ability to think creatively under constraints (no division allowed).
The Division Approach (If Allowed) and Why It Fails
If division were allowed, you could compute the total product of the array and then divide by each element. For nums = [1, 2, 3, 4], the total product is 24, so the result would be [24/1, 24/2, 24/3, 24/4] = [24, 12, 8, 6]. This runs in O(n) time and O(1) space.
But this approach breaks when the array contains zeros. If nums = [1, 2, 0, 4], the total product is 0, and dividing 0 by any element gives 0 — except at the zero index where you would need 1 * 2 * 4 = 8. You would need special-case handling for one zero versus two or more zeros.
Even with zero handling, this still uses division — which is explicitly banned. The interviewer wants to see the prefix-suffix approach, which handles all cases naturally without any division at all.
Prefix and Suffix Products — The Core LeetCode 238 Solution
The key insight is that the product of all elements except self at index i equals the product of all elements to the left of i multiplied by the product of all elements to the right of i. This naturally decomposes into two arrays: a left product array (prefix products) and a right product array (suffix products).
For nums = [1, 2, 3, 4], the left products array is [1, 1, 2, 6] — where leftProducts[i] is the product of all elements before index i. The right products array is [24, 12, 4, 1] — where rightProducts[i] is the product of all elements after index i.
The final answer at each index is leftProducts[i] * rightProducts[i]. So the result is [1*24, 1*12, 2*4, 6*1] = [24, 12, 8, 6]. This runs in O(n) time with O(n) space for the two auxiliary arrays.
- Build leftProducts by iterating left to right: leftProducts[0] = 1, then leftProducts[i] = leftProducts[i-1] * nums[i-1]
- Build rightProducts by iterating right to left: rightProducts[n-1] = 1, then rightProducts[i] = rightProducts[i+1] * nums[i+1]
- Multiply element-wise: result[i] = leftProducts[i] * rightProducts[i]
- Total: two passes for building, one pass for multiplying — three O(n) passes = O(n) time
Pro Tip
The O(1) space trick: use the output array to store left products first, then do a reverse pass with a running right product variable. Two passes, one array — elegant and space-optimal.
Product Except Self O(1) Extra Space Optimization
The O(n) space solution uses two extra arrays — but you can reduce to O(1) extra space (excluding the output array, which the problem says does not count). The trick is to use the output array itself as the left products array, then do a reverse pass with a single running variable for the right product.
First pass (left to right): fill the result array with prefix products. Set result[0] = 1. For each subsequent index, result[i] = result[i-1] * nums[i-1]. After this pass, result holds all the left products.
Second pass (right to left): initialize a variable rightProduct = 1. Walk backwards through the array. At each index, multiply result[i] by rightProduct, then update rightProduct = rightProduct * nums[i]. When the pass completes, result holds the final answer.
This approach uses exactly two passes and one output array — no additional data structures. It is the optimal solution that interviewers expect for LeetCode 238, running in O(n) time and O(1) extra space.
- 1Initialize result array of same length as nums, set result[0] = 1
- 2Left-to-right pass: for i = 1 to n-1, set result[i] = result[i-1] * nums[i-1]
- 3Initialize rightProduct = 1
- 4Right-to-left pass: for i = n-1 down to 0, set result[i] = result[i] * rightProduct, then rightProduct = rightProduct * nums[i]
- 5Return result — it now contains the product of all elements except self at each index
Edge Cases — Zeros, Negatives, and Single Elements
The prefix-suffix approach handles edge cases naturally, but it is important to understand how. If the array contains one zero, all products are zero except at the index where the zero sits — because that position multiplies all non-zero elements. The prefix-suffix approach gets this right automatically.
If the array contains two or more zeros, every product is zero — no index can avoid having at least one zero in its left or right product. Again, the approach handles this without any special logic.
Negative numbers also pose no issue. The product of an even number of negatives is positive, and an odd number of negatives is negative. The prefix-suffix multiplication preserves signs correctly.
For an array of length 1, the output is [1] (or however the problem defines it) since there are no other elements. For length 2, result = [nums[1], nums[0]] — each element is just the other element.
- One zero: all products are 0 except at the zero index — prefix-suffix handles this automatically
- Two+ zeros: every product is 0 — no special handling needed
- Negatives: sign propagation works naturally through multiplication
- Single element: result is [1] since there are no other elements to multiply
Watch Out
Watch out for zeros: if the array has one zero, all products are zero except at the zero's index. If there are two+ zeros, ALL products are zero. Handle these cases explicitly.
What Product of Array Except Self Teaches You
LeetCode 238 is a gateway problem to the prefix-suffix pattern — one of the most versatile techniques in array manipulation. Once you internalize the idea of decomposing a problem into "everything to the left" and "everything to the right," you will recognize it in dozens of other problems.
The bidirectional pass technique shows up in Trapping Rain Water (#42), where you compute left-max and right-max arrays. It appears in Best Time to Buy and Sell Stock variations, in Candy (#135), and in many interval and subarray problems. Mastering it here gives you a reusable tool.
The O(1) space optimization also teaches a general principle: when you need to build a result array anyway, see if you can repurpose it for intermediate computation. This mindset — reusing output space for working storage — applies well beyond this single problem.
Practice this problem with YeetCode flashcards to build the pattern recognition you need. When you see "product," "except self," or "no division," the prefix-suffix decomposition should be your first instinct.