Understanding Prefix Sums
Last Updated :
28 Jul, 2025
In programming, prefix sum arrays are a simple and powerful technique. They make it easier to solve problems that involve finding the sum of numbers between two points in an array or working with subarrays.
Prefix Sum Defination
A prefix sum array is a derived array where each element at index i represents the sum of the original array’s elements from index 0 to i.
Why is it called "prefix" ?
Because it deals with the "prefix" or beginning portion of the array. For any index i, the prefix sum at i is the total of all elements before or up to that point.
Mathematical Definition:
Let the original array be: arr[] = [a0, a1, a2, ..., an-i].
The prefix sum array is: prefix[i] = a0 + a1 + a2 + ... + ai
So,
- prefix[0] = arr[0]
- prefix[1] = arr[0] + arr[1]
- prefix[2] = arr[0] + arr[1] + arr[2]
- ...
Example:
Prefix Sum Implementation
We can build the prefix sum array in linear time (O(n)) with a single pass through the array.
- Initialize a prefix array of size n: Let prefix[0] = arr[0]
- Traverse the original array once and do prefix[i] = arr[i] + prefix[i-1]
C++
#include <iostream>
#include <vector>
using namespace std;
vector<int> buildPrefixSum(vector<int>& a) {
int n = a.size();
vector<int> prefix(n);
// initialize the first element
prefix[0] = a[0];
for (int i = 1; i < n; ++i) {
// add previous sum + current element
prefix[i] = prefix[i - 1] + a[i];
}
return prefix;
}
int main() {
vector<int> a = {2, 4, 6, 8, 10};
vector<int> prefix = buildPrefixSum(a);
for (int val : prefix) {
cout << val << " ";
}
cout << endl;
return 0;
}
Java
import java.util.ArrayList;
class GfG {
public static ArrayList<Integer> buildPrefixSum(int[] a) {
int n = a.length;
ArrayList<Integer> prefix = new ArrayList<>();
// initialize the first element
prefix.add(a[0]);
for (int i = 1; i < n; ++i) {
// add previous sum + current element
prefix.add(prefix.get(i - 1) + a[i]);
}
return prefix;
}
public static void main(String[] args) {
int[] a = {2, 4, 6, 8, 10};
ArrayList<Integer> prefix = buildPrefixSum(a);
for (int val : prefix) {
System.out.print(val + " ");
}
System.out.println();
}
}
Python
def build_prefix_sum(a):
n = len(a)
prefix = [0] * n
# initialize the first element
prefix[0] = a[0]
for i in range(1, n):
# add previous sum + current element
prefix[i] = prefix[i - 1] + a[i]
return prefix
if __name__ == "__main__":
a = [2, 4, 6, 8, 10]
prefix = build_prefix_sum(a)
for val in prefix:
print(val, end=" ")
print()
C#
using System;
using System.Collections.Generic;
class GfG {
public static List<int> buildPrefixSum(int[] a) {
int n = a.Length;
List<int> prefix = new List<int>();
// initialize the first element
prefix.Add(a[0]);
for (int i = 1; i < n; ++i) {
// add previous sum + current element
prefix.Add(prefix[i - 1] + a[i]);
}
return prefix;
}
public static void Main() {
int[] a = {2, 4, 6, 8, 10};
List<int> prefix = buildPrefixSum(a);
foreach (int val in prefix) {
Console.Write(val + " ");
}
Console.WriteLine();
}
}
JavaScript
function buildPrefixSum(a) {
let n = a.length;
let prefix = new Array(n);
// Initialize the first element
prefix[0] = a[0];
for (let i = 1; i < n; ++i) {
// add previous sum + current element
prefix[i] = prefix[i - 1] + a[i];
}
return prefix;
}
// Driver Code
let a = [2, 4, 6, 8, 101];
let prefix = buildPrefixSum(a);
for (let val of prefix) {
process.stdout.write(val + " ");
}
console.log();
Time Complexity: O(n), The algorithm traverses the input array once and performs constant-time additions.
Auxiliary Space: O(n), a separate array of size n is created to store prefix sums.
In-Place Prefix Sum
Instead of building a separate prefix array, we directly modify the input array: arr[i] = arr[i - 1] + arr[i];
This is space-efficient:
- Time Complexity: O(n)
- Space Complexity: O(1) extra space
C++
#include <iostream>
#include <vector>
using namespace std;
// function to build prefix sum in-place
vector<int> buildPrefixSum(vector<int>& arr) {
int n = arr.size();
for (int i = 1; i < n; ++i) {
// add previous sum + current element
arr[i] = arr[i - 1] + arr[i];
}
return arr;
}
int main() {
vector<int> arr = {2, 4, 6, 8, 10};
vector<int> res = buildPrefixSum(arr);
for (int val : res) {
cout << val << " ";
}
cout << endl;
return 0;
}
Java
import java.util.ArrayList;
class GfG {
// function to build prefix sum in-place
public static ArrayList<Integer> buildPrefixSum(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; ++i) {
// add previous sum + current element
arr[i] = arr[i - 1] + arr[i];
}
ArrayList<Integer> res = new ArrayList<>();
for (int val : arr) res.add(val);
return res;
}
public static void main(String[] args) {
int[] arr = {2, 4, 6, 8, 10};
ArrayList<Integer> res = buildPrefixSum(arr);
for (int val : res) {
System.out.print(val + " ");
}
System.out.println();
}
}
Python
# function to build prefix sum in-place
def build_prefix_sum(arr):
n = len(arr)
for i in range(1, n):
# add previous sum + current element
arr[i] = arr[i - 1] + arr[i]
return arr
if __name__ == "__main__":
arr = [2, 4, 6, 8, 10]
res = build_prefix_sum(arr)
for val in res:
print(val, end=" ")
print()
C#
using System;
using System.Collections.Generic;
class GfG {
// function to build prefix sum in-place
public static List<int> buildPrefixSum(int[] arr) {
int n = arr.Length;
for (int i = 1; i < n; ++i) {
// add previous sum + current element
arr[i] = arr[i - 1] + arr[i];
}
List<int> res = new List<int>(arr);
return res;
}
public static void Main() {
int[] arr = {2, 4, 6, 8, 10};
List<int> res = buildPrefixSum(arr);
foreach (int val in res) {
Console.Write(val + " ");
}
Console.WriteLine();
}
}
JavaScript
// function to build prefix sum in-place
function buildPrefixSum(arr) {
let n = arr.length;
for (let i = 1; i < n; ++i) {
// add previous sum + current element
arr[i] = arr[i - 1] + arr[i];
}
return arr;
}
// Driver Code
let arr = [2, 4, 6, 8, 10];
let res = buildPrefixSum(arr);
for (let val of res) {
process.stdout.write(val + " ");
}
console.log();
Applications of Prefix Sum
- Range sum queries
- Subarray problems: count subarrays with certain properties (e.g., sum, XOR)
- 2D prefix sums: used in image processing, matrix sum problems
- Sliding window optimizations
- Histogram-style range counting
Classic Problems That Use Prefix Sums
- Range Sum Query
- Subarray Sum Equals k
- Number of Subarrays with Sum ≤ k
- 2D Range Sum Queries
- Longest Subarray with Given Sum
Practical example to better understanding
Given an array arr[] of integers and a list of queries queries[][], where each query is in the form [L, R], compute the sum of elements from index L to R (both inclusive) for each query.
Examples:
Input: arr[] = [2, 4, 6, 8, 10], queries[][] = [[1, 3], [0, 2]]
Output: [18, 12]
Explanation:
Query [1, 3] → 4 + 6 + 8 = 18
Query [0, 2] → 2 + 4 + 6 = 12
Input: arr[] = [5, 1, 3, 2], queries[][] = [[0, 1], [2, 3]]
Output: [6, 5]
Explanation:
Query [0, 1] → 5 + 1 = 6
Query [2, 3] → 3 + 2 = 5
[Approach] Using Prefix Sum - O(n + q) Time and O(n) Space
The idea is to precompute a prefix sum array where each element at index i stores the sum of elements from index 0 to i.
This allows each query [L, R] to be answered in constant time using: sum = prefix[R] - prefix[L - 1] (or prefix[R] if L == 0).
Mathematics Behind the Prefix Sum Approach:
Let the original array be: arr[] = [a0, a1, a2, ..., an-1]
We define a prefix sum array prefix[] such that: prefix[i] = a0 + a1 + a2 + ... + ai
Now, to compute the sum of elements from index L to R, we use:
- If L > 0: sum(L, R) = prefix[R] - prefix[L - 1]
- If L == 0: sum(0, R) = prefix[R]
This works because:
- prefix[R] = a0 + a1 + ... + aL-1 + aL + ... + aR
- prefix[L - 1] = a0 + a1 + ... + aL-1
- So, prefix[R] - prefix[L - 1] = aL + aL+1 + ... + aR
C++
#include <iostream>
#include <vector>
using namespace std;
vector<int> rangeSumQueries(vector<int>& arr,
vector<vector<int>>& queries) {
int n = arr.size();
vector<int> prefix(n);
vector<int> result;
// build prefix sum array
prefix[0] = arr[0];
for (int i = 1; i < n; i++) {
prefix[i] = prefix[i - 1] + arr[i];
}
// process each query
for (auto& q : queries) {
int L = q[0], R = q[1];
int sum = prefix[R] - (L > 0 ? prefix[L - 1] : 0);
result.push_back(sum);
}
return result;
}
int main() {
vector<int> arr = {2, 4, 6, 8, 10};
vector<vector<int>> queries = {{1, 3}, {0, 2}};
vector<int> ans = rangeSumQueries(arr, queries);
for (int val : ans) {
cout << val << " ";
}
return 0;
}
Java
import java.util.ArrayList;
class GfG {
public static ArrayList<Integer> rangeSumQueries(int[] arr,
int[][] queries) {
int n = arr.length;
int[] prefix = new int[n];
ArrayList<Integer> result = new ArrayList<>();
// build prefix sum array
prefix[0] = arr[0];
for (int i = 1; i < n; i++) {
prefix[i] = prefix[i - 1] + arr[i];
}
// process each query
for (int[] q : queries) {
int L = q[0], R = q[1];
int sum = prefix[R] - (L > 0 ? prefix[L - 1] : 0);
result.add(sum);
}
return result;
}
public static void main(String[] args) {
int[] arr = {2, 4, 6, 8, 10};
int[][] queries = {{1, 3}, {0, 2}};
ArrayList<Integer> ans = rangeSumQueries(arr, queries);
for (int val : ans) {
System.out.print(val + " ");
}
}
}
Python
def rangeSumQueries(arr, queries):
n = len(arr)
prefix = [0] * n
result = []
# build prefix sum array
prefix[0] = arr[0]
for i in range(1, n):
prefix[i] = prefix[i - 1] + arr[i]
# process each query
for q in queries:
L, R = q[0], q[1]
sum = prefix[R] - (prefix[L - 1] if L > 0 else 0)
result.append(sum)
return result
if __name__ == "__main__":
arr = [2, 4, 6, 8, 10]
queries = [[1, 3], [0, 2]]
ans = rangeSumQueries(arr, queries)
for val in ans:
print(val, end=' ')
C#
using System;
using System.Collections.Generic;
class GfG {
public static List<int> rangeSumQueries(int[] arr,
int[][] queries) {
int n = arr.Length;
int[] prefix = new int[n];
List<int> result = new List<int>();
// build prefix sum array
prefix[0] = arr[0];
for (int i = 1; i < n; i++) {
prefix[i] = prefix[i - 1] + arr[i];
}
// process each query
foreach (var q in queries) {
int L = q[0], R = q[1];
int sum = prefix[R] - (L > 0 ? prefix[L - 1] : 0);
result.Add(sum);
}
return result;
}
public static void Main() {
int[] arr = {2, 4, 6, 8, 10};
int[][] queries = new int[][] {
new int[] {1, 3},
new int[] {0, 2}
};
List<int> ans = rangeSumQueries(arr, queries);
foreach (int val in ans) {
Console.Write(val + " ");
}
}
}
JavaScript
function rangeSumQueries(arr, queries) {
const n = arr.length;
const prefix = Array(n).fill(0);
const result = [];
// build prefix sum array
prefix[0] = arr[0];
for (let i = 1; i < n; i++) {
prefix[i] = prefix[i - 1] + arr[i];
}
// process each query
for (const q of queries) {
let L = q[0], R = q[1];
let sum = prefix[R] - (L > 0 ? prefix[L - 1] : 0);
result.push(sum);
}
return result;
}
// Driver Code
const arr = [2, 4, 6, 8, 10];
const queries = [[1, 3], [0, 2]];
const ans = rangeSumQueries(arr, queries);
for (const val of ans) {
process.stdout.write(val + " ");
}
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem