What space complexity measures
Space complexity is the amount of memory an algorithm needs as a function of its input size, written in the same Big O notation as time complexity and following the same rules: drop constants and lower-order terms, and describe growth, not exact bytes. The question is not "how many bytes?" but "how does the memory grow when the input grows?"
It helps to separate two parts. The input space is the memory the input itself occupies. The auxiliary space is the extra memory the algorithm allocates while it works, not counting the input. The total is input space plus auxiliary space. In interviews, "space complexity" most often means the auxiliary space, and problem statements say things like O(1) or O(n) extra space.
Constant space: O(1)
fn sum(a: i32, b: i32) -> i32 {
let sum = a + b;
sum
}
The function holds three integers: the two parameters and sum. That number does not depend on the values passed in, so the space is constant. Constant space is the goal for algorithms that can work with a few variables, such as a running total or a pair of indices.
Linear space: O(n)
fn generate(n: usize) -> Vec<usize> {
let mut numbers = Vec::new();
for i in 0..n {
numbers.push(i);
}
numbers
}
The vector numbers ends up with n elements, so the memory grows in step with n. Calling generate(5) returns [0, 1, 2, 3, 4]. The vector is also the output, but counting it is the safe default unless a problem says otherwise.
Quadratic space: O(n²)
fn generate(n: usize) -> Vec<Vec<usize>> {
let mut numbers = Vec::new();
for _ in 0..n {
let mut row = Vec::new();
for j in 0..n {
row.push(j);
}
numbers.push(row);
}
numbers
}
This builds a grid of n rows with n numbers each. For n = 3 the result is [[0, 1, 2], [0, 1, 2], [0, 1, 2]], nine numbers in total. The space is n × n, so it is O(n²). Tables for dynamic programming and adjacency matrices of graphs are typical examples.
Auxiliary space versus input space
fn sum(arr: &[i32]) -> i32 {
let mut sum = 0;
for n in arr {
sum += n;
}
sum
}
If the slice has n elements, the input space is O(n). The function adds two variables, sum and the loop variable n, so its auxiliary space is O(1). With [1, 2, 3] it returns 6. The slice parameter matters here: &[i32] borrows the caller's data, so the call copies nothing. Cloning is what costs space: arr.to_vec() or arr.clone() inside the function would add O(n) auxiliary space.
Recursion uses space too
Memory is not only the collections you create. Every function call that has not returned yet occupies a frame on the call stack. A recursive function that goes n calls deep uses O(n) space, even if it creates no vectors:
fn count_down(n: u32) -> u32 {
if n == 0 {
0
} else {
1 + count_down(n - 1)
}
}
count_down(1000) returns 1000 and keeps 1001 frames alive at the deepest point. The same count written as a loop would use O(1) space. The stack has a fixed size, so with a very large n the recursive version can overflow it and abort the program, whereas the loop cannot.
Rust specifics
- A
Vecreserves capacity in advance, so it may hold more memory than its length. That is a constant factor, so Big O ignores it. - A
HashSetorHashMapholding up tonentries isO(n)space. - Passing
&vor&mut vshares data without copying, and passing aVecby value moves it without allocating. Onlyclone(),to_vec()andcollect()into a new collection allocate. - Sorting with
sort_unstable()works in place, whilesort()may allocate a temporary buffer proportional to the length of the slice.
Common mistakes
- Counting the input as auxiliary space, or forgetting to say which one you are reporting.
- Forgetting the call stack in recursive solutions.
- Assuming every
clone()is free. - Saying
O(n)for a loop variable: a single counter isO(1)no matter how many iterations it counts.
Key takeaways
- Space complexity measures how memory grows with the input:
O(1)for a fixed number of variables,O(n)for a collection ofnitems,O(n²)for ann × ngrid. - Space complexity is auxiliary space plus input space; the extra memory the algorithm adds is usually what is meant.
- Recursion depth counts as space.
