← Back to section

Pattern 4: Prefix and Suffix

Pay O(n) once to precompute running totals β€” and then answer questions about any slice of the array in O(1) each.

🎯

Try it first: Product of Array Except Self

Before reading the theory, try to solve it. You can start with brute force, you can fail β€” the point is to feel the problem. The theory comes right below.

Return an array where answer[i] is the product of all elements except nums[i]. Without using division, in O(n).

Example: nums = [1, 2, 3, 4] β†’ [24, 12, 8, 6].

Carregando editor…

Did you try? Most people think of "total product Γ· nums[i]" β€” but the statement forbids division (and it would break with zeros). The brute force without division multiplies the other nβˆ’1 elements for each i: O(nΒ²). The theory below solves it in O(n) by decomposing "everything except i" into left Γ— right.

The theory: what problem does prefix solve?

Think of an array of sums. How much does it cost to answer "what is the sum of the slice between i and j?". The naive way, O(n) per question β€” and a problem that asks n questions becomes O(nΒ²).

The waste: each question re-sums elements that were already summed in previous questions. The solution is to accumulate once and reuse forever:

prefix[i] = sum of ALL elements before position i
prefix[0] = 0 (there's nothing before the start)

sum of the slice [i..j] = prefix[j + 1] - prefix[i]

Why does the subtraction work? prefix[j+1] sums everything up to j; prefix[i] sums everything before i. The difference is exactly the core [i..j] β€” any slice, in one subtraction: O(1) per question after O(n) of preparation.

The signals in the statement

  • Repeated questions about sums/products of slices ("range sum").
  • "For each position, consider all the rest" β€” everything to the left Γ— everything to the right.
  • "How many subarrays sum to exactly k?" β€” prefix combined with a hash map.
  • Contiguous subarrays with negative numbers (where sliding window broke, remember?).

Prefix + hash map: the combo

Here's the prettiest connection between the lessons. "How many subarrays sum to k?": every subarray [i..j] with sum k satisfies prefix[j+1] - prefix[i] = k, that is: prefix[i] = prefix[j+1] - k.

Walk through the array accumulating the sum and ask the hash map: "how many times have I already seen the prefix current_sum - k?" β€” it's the Two Sum template, applied to prefixes! Ask the past, record for the future. O(n) total for a problem whose brute force is O(nΒ²). (Keep this combo in mind: it'll be useful soon... πŸ˜‰)

Example β€” Product of Array Except Self

"Return an array where answer[i] is the product of all elements, EXCEPT nums[i] β€” without using division, in O(n)."

  • Brute force: for each i, multiply the other n-1 elements β€” O(nΒ²).
  • The temptation: total product Γ· nums[i]. Besides being forbidden by the statement, division breaks with zeros (division by zero, and with two zeros everything is zero).
  • The pattern: "everything except i" = (everything to the left of i) Γ— (everything to the right of i). They're exactly a prefix and a suffix of products!
pass 1 (left β†’ right): answer[i] = product of everything before i
pass 2 (right β†’ left): answer[i] *= product of everything after i

Watch the two passes in the visualizer β€” notice the prefix accumulator filling answer on the way out, and suffix completing it on the way back:

ExecuΓ§Γ£o real, gravada passo a passo
Carregando Python no navegador (primeira vez demora alguns segundos)…

Why is it O(n)? And why is the space O(1)?

  • Time: two passes in sequence β€” O(n) + O(n) = O(n) (rule 1: sequences add, constants drop).
  • Space: the subtle trick β€” instead of creating arrays prefix[] and suffix[] (O(n) each), we carry a single scalar accumulator in each pass and write directly into answer. Since the answer array doesn't count as extra space (it IS the answer), the extra is two variables: O(1).
SolutionTimeExtra spaceWhy
Brute forceO(nΒ²)O(1)n products of n-1 factors
DivisionO(n)O(1)❌ breaks with zeros (and is forbidden)
Prefix + suffix arraysO(n)O(n)two auxiliary arrays
Accumulators across 2 passesO(n)O(1)writes directly into the answer

Generalize: prefix isn't only about sums

The running total can be any operation that builds from left to right: sum, product, maximum ("largest element so far"), count ("how many pairs so far"). You already used one without realizing: the min_price from the previous lesson was a prefix minimum carried as a scalar! And the suffix is the same movie back to front.

🧠 Review quiz

0/4

1. With the prefix array ready, why does the sum of ANY slice [i..j] cost O(1)?

2. In Product Except Self, why doesn't 'total product divided by nums[i]' work?

3. How does the final version of Product Except Self achieve O(1) extra space?

4. 'How many contiguous subarrays sum to exactly k?' (with negatives). What's the O(n) strategy?

Summary

  • Prefix = pay O(n) once, answer slices in O(1) forever.
  • "Everything except i" = prefix(left) Γ— suffix(right) β€” two passes.
  • Scalar accumulator + writing into the answer = O(1) extra space.
  • Prefix + hash map solves counting subarrays with sum k β€” including with negatives.

Next lesson: the section's last pattern and the most elegant β€” Kadane, the local decision that solves the maximum subarray in a single pass.