DSA course menu
Space Complexity Explained (With Python Examples)
Learn space complexity: how much extra memory an algorithm needs, in-place versus extra-space solutions, the memory cost of recursion, and the time-memory trade-off.
On this page
Space complexity describes how much extra memory an algorithm needs as the input grows. It uses the same Big O notation as time.
We usually count only the auxiliary space: memory the algorithm creates itself, not the input it was given.
O(1) space: a few variables#
def find_max(items):
best = items[0] # one variable
for x in items:
if x > best:
best = x
return best
print(find_max([3, 17, 8, 21, 5]))21However long the list is, the function only ever keeps best and x. That is O(1) extra space.
O(n) space: building something as big as the input#
def squares(items):
result = []
for x in items:
result.append(x * x) # result grows to n items
return result
print(squares([1, 2, 3, 4]))[1, 4, 9, 16]The new list has one entry per input item: O(n) space.
In-place algorithms#
An in-place algorithm changes the input directly instead of building a copy. Reversing a list both ways:
def reversed_copy(items):
return items[::-1] # new list: O(n) space
def reverse_in_place(items):
left, right = 0, len(items) - 1
while left < right: # O(1) space: two indexes
items[left], items[right] = items[right], items[left]
left += 1
right -= 1
data = [1, 2, 3, 4, 5]
print(reversed_copy(data), data)
reverse_in_place(data)
print(data)[5, 4, 3, 2, 1] [1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]The copy leaves data unchanged but needs n extra slots. The in-place version needs only two indexes, but it modifies the caller's list. Which one is right depends on whether the caller still needs the original.
Recursion uses memory too#
Every recursive call waits on the call stack until the calls below it return. A recursion that goes n levels deep uses O(n) space, even with no lists in sight:
import sys
def depth(n):
if n == 0:
return 0
return 1 + depth(n - 1)
print(depth(500))
print("Python's default recursion limit:", sys.getrecursionlimit())500
Python's default recursion limit: 1000Asking for depth(5000) would raise RecursionError, because Python stops the stack at its limit. A loop that does the same counting needs O(1) space. More on this in Recursion.
The time-memory trade-off#
Spending memory often saves time. Answering "how many times does each word appear?" for many queries:
text = "the cat and the hat and the bat"
words = text.split()
# Option 1: no extra memory, O(n) per question
print(words.count("the"))
# Option 2: O(n) memory once, then O(1) per question
counts = {}
for w in words:
counts[w] = counts.get(w, 0) + 1
print(counts["the"], counts["and"])3
3 2If you ask one question, counting directly is fine. If you ask thousands, building the dictionary once is far faster overall.
Common mistakes#
Practice#
Practice exercise
Write running_total(items) that replaces each item with the sum of itself and all items before it, in place, using O(1) extra space. For [1, 2, 3, 4] the list should become [1, 3, 6, 10].
Show hint
Go from left to right. Each item becomes itself plus the (already updated) item before it.
Show solution
def running_total(items):
for i in range(1, len(items)):
items[i] += items[i - 1]
data = [1, 2, 3, 4]
running_total(data)
print(data)[1, 3, 6, 10]Only the loop variable i is created, so the extra space is O(1); the time is O(n). This idea, a prefix sum, gets its own lesson in Prefix Sums.
Key takeaway#
Next: functions that call themselves, in Recursion.
Finished this lesson?
Related lessons
Recommended DSA resources
- Cracking the Coding Interview by Gayle Laakmann McDowell
189 practice questions with solutions, for coding interview preparation.
Some links are affiliate links. If you buy through them, Laviyx Learn may earn a commission at no extra cost to you. As an Amazon Associate, we earn from qualifying purchases.