LeetCode ยท #238

Product of Array Except Self Solution

Given an integer array nums, return an array answer where answer[i] is the product of all elements except nums[i]. You must solve it without using division and in O(n) time.

01
Section One ยท Problem

Problem Statement

๐Ÿท๏ธ

Difficulty

Medium

๐Ÿ”—

LeetCode

Problem #238

๐Ÿ—๏ธ

Pattern

Prefix Sum โ€” prefix & suffix products

Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i]. The algorithm must run in O(n) time and must not use the division operation.

Example
Input: nums = [1, 2, 3, 4] Output: [24, 12, 8, 6] // answer[0] = 2ร—3ร—4 = 24, answer[1] = 1ร—3ร—4 = 12, ...
Example 2
Input: nums = [-1, 1, 0, -3, 3] Output: [0, 0, 9, 0, 0] // Zero at index 2 zeros out all other positions; answer[2] = (-1)ร—1ร—(-3)ร—3 = 9
Constraints
โ€ข 2 โ‰ค nums.length โ‰ค 10โต โ€ข -30 โ‰ค nums[i] โ‰ค 30 โ€ข The product of any prefix or suffix fits in a 32-bit integer โ€ข You must NOT use division โ†‘ Key constraint โ€” forces prefix/suffix approach
02
Section Two ยท Approach 1

Brute Force โ€” O(nยฒ)

For each index i, multiply all other elements together. Two nested loops โ€” the outer selects the position, the inner computes the product of everything except that position.

Why it works

Directly implements the definition: answer[i] = โˆ nums[j] for all j โ‰  i. Correct by construction โ€” every non-self element is multiplied.

Why we can do better
Problem: Each element's product is computed independently, repeating most of the multiplication. The product of elements to the left of index i overlaps heavily with index i-1. Prefix and suffix products precompute these running products, reducing repeated work from O(n) per element to O(1).
Java โ€” Brute Force
class Solution { public int[] productExceptSelf(int[] nums) { int n = nums.length; int[] answer = new int[n]; for (int i = 0; i < n; i++) { int product = 1; for (int j = 0; j < n; j++) { if (j != i) product *= nums[j]; } answer[i] = product; } return answer; } }
Python โ€” Brute Force
class Solution: def productExceptSelf(self, nums: list[int]) -> list[int]: n = len(nums) answer = [1] * n for i in range(n): product = 1 for j in range(n): if j != i: product *= nums[j] answer[i] = product return answer
MetricValue
TimeO(nยฒ) โ€” n multiplications per element
SpaceO(1) โ€” excluding the output array
03
Section Three ยท Approach 2

Prefix & Suffix Products โ€” O(n)

The product of all elements except nums[i] equals product of everything to the left ร— product of everything to the right. Compute running prefix products left-to-right, then multiply in suffix products right-to-left โ€” all in the output array itself.

๐Ÿ’ก Mental model: Imagine you're standing in a line of people, each holding a number. You want to know the product of everyone else's number โ€” without asking each person individually. Instead, a runner goes left-to-right whispering "the product of everyone to your left is X." Then a second runner goes right-to-left whispering "multiply by Y โ€” the product of everyone to your right." Each person now has the complete product of all others. Two passes, no division.
Algorithm โ€” Two-pass prefix/suffix
  • Step 1: Initialize answer[i] = 1 for all i.
  • Step 2: Left pass โ€” maintain a running prefix = 1. For each i from 0 to nโˆ’1: set answer[i] = prefix, then prefix *= nums[i].
  • Step 3: Right pass โ€” maintain a running suffix = 1. For each i from nโˆ’1 to 0: set answer[i] *= suffix, then suffix *= nums[i].
  • Step 4: Return answer โ€” each slot now holds left-product ร— right-product.
๐ŸŽฏ When to recognize this pattern:
  • Any time a problem asks for a value that depends on all other elements (excluding the current one) โ€” think prefix/suffix decomposition.
  • The signal is "for each index, compute something from left side AND right side." This pattern appears in LC 238, LC 42 (Trapping Rain Water โ€” prefix max + suffix max), LC 135 (Candy โ€” left and right passes), and range-product queries.
Why no extra arrays needed:
  • The output array itself stores the prefix products from the left pass.
  • The right pass multiplies suffix products directly into the output.
  • We only need one extra variable (suffix) as we sweep right-to-left โ€” achieving O(1) extra space beyond the required output.
04
Section Four ยท Trace

Visual Walkthrough

Trace through nums = [1, 2, 3, 4]:

Prefix & Suffix Products โ€” two passes building the answer
INPUT ARRAY 1 [0] 2 [1] 3 [2] 4 [3] Left Pass โ†’ (prefix products) prefix starts at 1, stored BEFORE multiplying current element i=0: answer[0] = prefix = 1, then prefix = 1ร—1 = 1 i=1: answer[1] = prefix = 1, then prefix = 1ร—2 = 2 i=2: answer[2] = prefix = 2, then prefix = 2ร—3 = 6 i=3: answer[3] = prefix = 6, then prefix = 6ร—4 = 24 answer[] after left pass: 1 1 2 6 โ† Right Pass (suffix products multiplied in) suffix starts at 1, multiplied INTO answer BEFORE updating suffix i=3: answer[3] = 6 ร— suffix(1) = 6, then suffix = 1ร—4 = 4 i=2: answer[2] = 2 ร— suffix(4) = 8, then suffix = 4ร—3 = 12 i=1: answer[1] = 1 ร— suffix(12) = 12, then suffix = 12ร—2 = 24 i=0: answer[0] = 1 ร— suffix(24) = 24, then suffix = 24ร—1 = 24 FINAL answer[]: 24 12 8 6 Answer: [24, 12, 8, 6] โœ“
Notice:
  • Two linear passes โ€” no nested loops.
  • The left pass builds "product of everything before me." The right pass multiplies in "product of everything after me." Each element's final value is left ร— right โ€” the product of all others.
05
Section Five ยท Implementation

Code โ€” Java & Python

Java โ€” Prefix/Suffix in-place
class Solution { public int[] productExceptSelf(int[] nums) { int n = nums.length; int[] answer = new int[n]; // Left pass โ€” answer[i] holds product of all elements left of i int prefix = 1; for (int i = 0; i < n; i++) { answer[i] = prefix; prefix *= nums[i]; // include current for next position } // Right pass โ€” multiply suffix product into each position int suffix = 1; for (int i = n - 1; i >= 0; i--) { answer[i] *= suffix; suffix *= nums[i]; // include current for next position } return answer; } }
Python โ€” Prefix/Suffix in-place
class Solution: def productExceptSelf(self, nums: list[int]) -> list[int]: n = len(nums) answer = [1] * n # Left pass โ€” prefix products prefix = 1 for i in range(n): answer[i] = prefix prefix *= nums[i] # Right pass โ€” multiply suffix products in suffix = 1 for i in range(n - 1, -1, -1): answer[i] *= suffix suffix *= nums[i] return answer
06
Section Six ยท Analysis

Complexity Analysis

Approach Time Space Trade-off
Brute Force O(nยฒ) O(1) Correct but too slow for n = 10โต
Total Product รท current O(n) O(1) Violates the "no division" constraint; fails on zeros
Prefix/Suffix โ† optimal O(n) O(1)* Two passes, no division. *O(1) extra beyond output array.
Why not division?:
  • Division seems tempting โ€” compute total product, then answer[i] = total / nums[i].
  • But: (1) the problem explicitly forbids it, (2) zeros break it โ€” dividing by zero is undefined, and you'd need special-case handling for one or more zeros.
  • The prefix/suffix approach handles zeros naturally because it never divides.
07
Section Seven ยท Edge Cases

Edge Cases & Pitfalls

Case Input Why It Matters
Contains one zero [1, 2, 0, 4] Only the zero's position gets a non-zero product (1ร—2ร—4=8). All others become 0.
Contains two zeros [0, 2, 0, 4] Every position includes at least one zero โ†’ entire answer is [0, 0, 0, 0].
Negative numbers [-1, 2, -3, 4] Sign handling is automatic โ€” multiplication preserves sign correctly.
Two elements [3, 5] Minimum input. answer = [5, 3] โ€” each is the other's value.
All ones [1, 1, 1, 1] Every product is 1. Prefix/suffix stays 1 throughout โ€” the identity case.
Large array n = 10โต, values in [-30, 30] Guaranteed to fit in 32-bit int per constraints. No overflow concern.
โš  Common Mistake: Confusing the order of operations in the left pass โ€” storing prefix into answer[i] before multiplying prefix *= nums[i]. If you multiply first, you include nums[i] in its own product. The correct sequence is: store, then update. Same rule applies in the right pass.

โ† Back to Arrays & Hashing problems