ESC

Type to search the knowledge base.

Product of Array Except Self

Output[i] = product of all nums except i — prefix/suffix passes, O(n) time without division.

intermediate3 min read
  • dsa
  • arrays
  • interview
  • Google
  • Meta
  • Amazon

The problem

Given nums, return answer where answer[i] equals the product of every element except nums[i]. O(n) time, no division, and ideally O(1) extra space (output array free).

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

Input:  nums = [-1,1,0,-3,3]
Output: [0,0,9,0,0]

Brute force

For each i, multiply all j ≠ i. O(n²). Division approach: total product / nums[i] — fails on zeros and is banned.

function productExceptSelfBrute(nums: number[]): number[] {
  const n = nums.length;
  const out = Array(n).fill(1);
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      if (i !== j) out[i] *= nums[j];
    }
  }
  return out;
}

Optimal: prefix × suffix

answer[i] = (product left of i) × (product right of i).

Two-array version first, then compress:

function productExceptSelf(nums: number[]): number[] {
  const n = nums.length;
  const out = Array(n).fill(1);

  // out[i] = prefix product before i
  let pref = 1;
  for (let i = 0; i < n; i++) {
    out[i] = pref;
    pref *= nums[i];
  }

  // multiply by suffix product after i
  let suff = 1;
  for (let i = n - 1; i >= 0; i--) {
    out[i] *= suff;
    suff *= nums[i];
  }

  return out;
}
Time O(n)
Space O(1) extra (not counting out)

Walk [1,2,3,4]

After prefix: [1, 1, 2, 6]
Suffix multiplies: ×24, ×12, ×4, ×1 → [24, 12, 8, 6]

Edge cases

  • Zeros: one zero → only that index gets non-zero product; two zeros → all zeros
  • Negatives — product signs just work
  • Single element — constraints usually n ≥ 2
  • Large products — JS number precision; mention BigInt if values huge

Common bugs

  • Including nums[i] in its own product
  • Using division and crashing on zero
  • Off-by-one on prefix/suffix loops
  • Second pass overwriting before multiplying

Interview delivery

  1. No division, O(n).
  2. Prefix then suffix.
  3. In-place into output.
  4. Trace with a zero in the array.
  5. O(1) extra space claim carefully.

Two zeros case

nums = [0,0,2] → every product includes at least one zero → [0,0,0]. One zero at index i → only out[i] is non-zero (product of the rest).

Why division is banned

Even if allowed, zeros break total/nums[i]. You’d special-case zero counts — messier than prefix/suffix and fails the spirit of the problem.

In-place constraint

Output array doesn’t count as extra space per LC. Using two full prefix/suffix arrays is O(n) extra — fine as a first version, then compress to one output + running suffix.

Further reading