SECTION 1
Historical Context & Motivation
Imagine you are building a weather app that stores the daily rainfall for an entire year. A user asks, "How much rain fell between March 15 and June 30?" The brute-force approach would loop through every day in that range and add up the values. That works, but what if thousands of users each ask about different date ranges every second? Looping each time quickly becomes too slow.
The idea of prefix sums — also called cumulative sums — has roots in early computing and mathematics. Mathematicians have long used cumulative totals in statistics and calculus, and computer scientists adopted the technique as soon as array-based computation became practical. The pattern is so fundamental that it appears in database engines, image processing, and competitive programming alike.
1940s • Cumulative Distribution Functions
1960s • Early Array Algorithms
1984 • Summed-Area Table (SAT)
2000s • Competitive Programming Boom
The central question prefix sums answer is: How can we answer many range-sum queries on the same array without re-adding elements each time? By spending a small amount of work up front, we can reduce every future query to a single subtraction.
SECTION 2
Core Principles & Definitions
A prefix sum array is a helper array where each element stores the sum of all original elements from the start up to (and including) that index. Once built, you can find the sum of any contiguous sub-range in constant time — no loop required. The core ideas break down into a few simple principles.
Pre-computation
Range Query Formula
Trade-off: Space for Speed
Static Data Assumption
KEY TAKEAWAY
SECTION 3
Visual Explanation
The diagram below shows how an original array is transformed into its prefix sum array, and then how a range query is answered by a single subtraction.
Notice how the prefix array at index i always equals the sum of arr[0] through arr[i]. To get the sum from index L to R, you take pre[R] − pre[L − 1]. If L is 0, you just use pre[R] directly since there is nothing to subtract. This single subtraction replaces what could be a loop over thousands of elements.
SECTION 4
Mathematical Framework
Let's formalize the two operations — building the prefix array and querying a range — with clear formulas and their Big-O complexities.
PREFIX ARRAY CONSTRUCTION
Where arr is the original array of length n, and pre is the prefix sum array. Building this takes O(n) time.
RANGE SUM QUERY
L is the left index and R is the right index (both inclusive). Each query takes O(1) time — constant, regardless of range size.
TOTAL COMPLEXITY
Compare this to brute force, which costs O(n × Q) in the worst case. For large n and Q, the prefix sum approach is dramatically faster.
Common Pitfall: Off-by-One Errors
pre with length n + 1, where pre[0] = 0 and pre[i] = pre[i − 1] + arr[i − 1]. Then the query becomes simply pre[R + 1] − pre[L], which is cleaner and avoids the special case when L = 0.SECTION 5
Java Implementation & Walk-Through
Below is a complete Java implementation showing both the construction of the prefix sum array and range queries. We use the size n + 1 trick so that every query follows the same formula with no special cases.
pre[R+1] − pre[L] works uniformly, even when L is 0.Notice the key detail: the prefix array pre has n + 1 elements. The extra slot at index 0 holds 0, which represents the sum of zero elements. This means pre[i+1] equals the sum of arr[0] through arr[i]. When you compute pre[R+1] − pre[L], the formula naturally handles every case including L = 0. You never need an if-statement to check for the boundary.
| Index i | arr[i] | pre[i] (size n+1) | Meaning of pre[i] |
|---|---|---|---|
| 0 | — | 0 | Sum of 0 elements |
| 1 | 2 (arr[0]) | 2 | Sum of arr[0..0] |
| 2 | 5 (arr[1]) | 7 | Sum of arr[0..1] |
| 3 | 1 (arr[2]) | 8 | Sum of arr[0..2] |
| 4 | 8 (arr[3]) | 16 | Sum of arr[0..3] |
| 5 | 3 (arr[4]) | 19 | Sum of arr[0..4] |
| 6 | 7 (arr[5]) | 26 | Sum of arr[0..5] |
Complete mapping between original array indices and the size n+1 prefix sum array
SECTION 6
Worked Example
A teacher records daily quiz scores for a student over one week: int[] scores = {88, 92, 75, 95, 83, 90, 78}. She wants to quickly answer questions like "What was the total score from Tuesday (index 1) to Friday (index 4)?" Let's solve this step by step using a prefix sum array.
Range Sum of Quiz Scores
- 1
Step 1 — Identify the Data
The original array is scores = {88, 92, 75, 95, 83, 90, 78} with n = 7. We need the sum from L = 1 to R = 4 (Tuesday through Friday). - 2
Step 2 — Build the Prefix Sum Array (size n + 1 = 8)
Start with pre[0] = 0. Then: pre[1] = 0 + 88 = 88, pre[2] = 88 + 92 = 180, pre[3] = 180 + 75 = 255, pre[4] = 255 + 95 = 350, pre[5] = 350 + 83 = 433, pre[6] = 433 + 90 = 523, pre[7] = 523 + 78 = 601.pre = [0, 88, 180, 255, 350, 433, 523, 601] - 3
Step 3 — Apply the Range Query Formula
sum(L, R) = pre[R + 1] − pre[L]. Substituting L = 1 and R = 4: sum(1, 4) = pre[5] − pre[1] = 433 − 88.sum(1, 4) = 345 - 4
Step 4 — Verify by Direct Addition
Adding scores[1] through scores[4] directly: 92 + 75 + 95 + 83 = 345. The answer matches, confirming the prefix sum approach is correct.✓ Verified: 345 - 5
Step 5 — Answer a Second Query for Free
Now the teacher asks for the total from Wednesday (index 2) to Sunday (index 6). Using the same prefix array: sum(2, 6) = pre[7] − pre[2] = 601 − 180 = 421. No extra loops needed — we reused the prefix array.sum(2, 6) = 421
SECTION 7
Strengths, Limitations & Comparisons
Prefix sums are a powerful tool, but every tool has its limits. The table below compares the brute-force approach with prefix sums across several dimensions so you can see when each one is appropriate.
| Feature | Brute-Force Loop | Prefix Sum Array |
|---|---|---|
| Pre-processing time | None (O(0)) | O(n) — one pass |
| Per-query time | O(n) worst case | O(1) |
| Total for Q queries | O(n × Q) | O(n + Q) |
| Extra memory | None | O(n) |
| Handles updates? | Yes — always reads fresh data | No — must rebuild after changes |
| Best when... | Only 1 or 2 queries needed | Many queries on static data |
Brute-force vs. prefix sum comparison
WHEN TO USE PREFIX SUMS
SECTION 8
Connection to Advanced Techniques
The prefix sum pattern is a stepping stone toward several more advanced data structures and algorithms. Understanding this foundation makes learning those topics far easier.
| Technique | What It Adds | Use Case |
|---|---|---|
| 2-D Prefix Sums | Extends the idea to a grid (matrix). Each cell stores the sum of the rectangle from (0,0) to (r,c). | Image processing, sub-rectangle sum queries |
| Difference Array | The inverse of prefix sums. Stores differences between consecutive elements; a prefix sum of the difference array recovers the original. | Efficiently applying range updates (add k to every element from L to R) |
| Fenwick Tree (BIT) | A tree structure that supports both point updates and prefix queries in O(log n) time. | Dynamic data where both queries and updates happen frequently |
| Segment Tree | A balanced binary tree that answers arbitrary range queries (min, max, sum, GCD, etc.) in O(log n) with updates. | Competitive programming, database engines |
Where prefix sums lead — related data structures
Each of these more advanced tools builds on the intuition you now have: pre-compute cumulative information so that queries become fast. Mastering the basic prefix sum array is your first step into this powerful family of techniques. If you go on to take AP Computer Science A or participate in competitive programming, you will see these ideas again and again.
SECTION 9
Practice Problems
Question 1: CONCEPTUAL
Show answer
Question 2: BASIC CALCULATION
Show answer
Question 3: INTERMEDIATE
Show answer
Question 4: APPLIED
Show answer
Question 5: CRITICAL THINKING
Show answer
SUMMARY
Lesson Summary
Summary
A prefix sum array stores cumulative totals so that any range sum query can be answered in O(1) time with a single subtraction. Building the array takes O(n) pre-processing and O(n) extra space. The core formula using the n + 1 convention is sum(L, R) = pre[R + 1] − pre[L], which avoids off-by-one errors and handles every boundary case cleanly.
This technique excels when the data is static (unchanging) and many queries are needed. For dynamic data, consider a Fenwick tree or segment tree. The prefix sum pattern also extends to two dimensions (2-D prefix sums) and has a natural inverse in the difference array technique. Master this foundational pattern, and you'll have a reliable tool for a wide variety of array problems.