Master the O(n) prefix-suffix pattern to solve LeetCode 238 without division.
If you’ve been grinding LeetCode for interviews at Amazon, Apple, or Facebook, you’ve probably run into this one. LeetCode 238 - “Product of Array Except Self” - is one of those problems that looks deceptively simple until you read the constraints.
Here’s what you need to do: take an array nums and create a new array where each element at index i equals the product of all the other elements in the original array. Everything except the element at i.
The catch? You’ve got to do this in O(n) time, and—here’s the kicker—you can’t use division.
Yeah, I know. That second constraint changes everything.
Analogy: The Secret Gift Pool
Think about this scenario: you and 3 friends are pooling money for a gift. Everyone puts cash in an envelope, but you want to know how much everyone else contributed—without counting your own money.
This is basically what we’re doing with the array problem.
Look, the obvious solution is to multiply everything together, then divide by each element. Simple, right?
Wrong. And not just because the problem says we can’t.
Here’s the thing: if your array contains even one zero, the entire product becomes 0. Now what? You’d need to divide by zero for that element, which is… well, mathematically impossible. Your program crashes, or you end up writing a bunch of messy exception handling code.
Critical Failure: With nums = [1, 2, 0, 4], the total product is 0. When you try to calculate the answer for the zero element, you’re doing 0 / 0. That’s undefined, and your code explodes.
Let me show you what the division approach looks like (and where it falls apart):
Note: This approach uses division, which is typically not allowed in the problem constraints. This is for educational purposes to understand the concept.
Since division is off the table, we need a different approach. Let’s break down what we’re actually calculating for each position.
For any index i, the answer is:
i multiplied togetheri multiplied togetherThat’s it. We’re just splitting the problem in two.
Answer[i] = (Product of nums[0...i-1]) Ă— (Product of nums[i+1...n-1])
(If you’re at the start or end of the array, the “empty” side just counts as 1.)
The straightforward way to do this is to pre-calculate two arrays:
Left[i]: Product of everything from index 0 to i-1Right[i]: Product of everything from index i+1 to n-1Then multiply Left[i] * Right[i] for your answer. Done.
This works perfectly. But can we do better?
Here’s where it gets clever. We’re using O(n) extra space for those Left and Right arrays. But what if we could do this with just the output array and a couple of variables?
Space Optimization Trick: Store the prefix products directly in the output array, then multiply by a running suffix variable in a second pass. No extra arrays needed.
Let’s break this down step by step:
answer array (same length as input)answer[0] = 1 (nothing to the left of the first element)answer[i] (the prefix) by this suffixIt’s like we’re painting the answer in two coats—first the left products, then we layer the right products on top.
Alright, here’s the code for the space-optimized solution. Remember, the problem says the output array doesn’t count toward space complexity (which is nice of them).
class Solution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] answer = new int[n];
// Left pass: answer[i] will contain the product of all elements to the left of i
answer[0] = 1;
for (int i = 1; i < n; i++) {
answer[i] = answer[i - 1] * nums[i - 1];
}
// Right pass: R contains the product of all elements to the right of i
int R = 1;
for (int i = n - 1; i >= 0; i--) {
// Multiply the prefix product (already in answer[i]) by the suffix product R
answer[i] = answer[i] * R;
// Update R to include nums[i] for the next iteration
R *= nums[i];
}
return answer;
}
} Time Complexity: O(N)
We make two passes through the array—one forward, one backward. That’s O(2N), which simplifies to O(N). Linear time, just like the problem asked for.
Space Complexity: O(1)
We’re using the output array, but the problem explicitly says that doesn’t count as extra space. Beyond that, we’ve only got a handful of variables (R, i, n). The earlier version with separate Left and Right arrays would be O(N) space, which is why this optimization matters.
Forgetting to initialize with 1: If you start your accumulator at 0, the entire product chain becomes zero. Not fun to debug.
Off-by-one errors: Your prefix loop should start at index 1 (since you’re looking back at i-1), and your suffix loop starts at n-1. Get these wrong and you’ll be scratching your head for a while.
The zero cases (this is actually kind of cool):
0The beautiful part? Our algorithm handles all of these automatically. No special if statements needed.
This problem is a perfect example of how thinking in terms of “what’s to my left” and “what’s to my right” can crack open array problems that seem impossible at first glance. The prefix/suffix pattern shows up everywhere—you’ll see it again in problems like “Trapping Rain Water” and “Candy.”
Once you get comfortable with this approach, you’ll start spotting opportunities to use it all over the place. And that’s when array problems start feeling less like puzzles and more like patterns you recognize.
Now go ace that interview.