Measuring Space Complexity
Imagine a Turing machine that must decide whether a graph has a path between two vertices. But the machine is only handed a stub of scratch memory. This is far less than the size of the input itself. Can it still work? Answering this requires a precise way to measure space the way we already measure time. This turns out to be subtler than counting steps. Space can be reused. So a machine can run for an astronomically long time while touching only a tiny amount of memory. This gap between time and space is one of the deepest phenomena in computation. Space usage matters because memory, unlike time, is a physical resource. It is often the binding constraint in real systems. Embedded devices, streaming algorithms, and cache-conscious database engines all live or die by how little working memory they need. This holds independent of how long they may run. Complexity theory captures this by defining a model where the input is read-only. It does not count against the space budget. A separate work tape — the true memory the algorithm consumes — is what gets measured instead. This single modeling choice is what makes sublinear space meaningful. Sublinear space means space smaller than the input size. Without this choice, it would be a non-trivial notion rather than an impossibility. This article builds the formal machinery for measuring space. It covers the multi-tape Turing machine model with a read-only input tape. It defines . It also covers the crucial convention that lets us discuss machines using less space than it takes to even write down the input. We prove basic closure and comparison facts. We work through a careful example: a sublinear-space algorithm for testing whether a string is a palindrome. We also catalog the pitfalls that trip up students first learning this model. This is especially true for the temptation to let the input tape "count" as memory. By the end, you will have the exact vocabulary and proof techniques you need. These will let you state and later prove the landmark results built on this foundation. These include the classes and , and Savitch's Theorem relating deterministic and nondeterministic space. They also include PSPACE as the space analogue of P. Finally, they include the Space Hierarchy Theorem, showing that more space provably buys more power.
- Space complexity measures work-tape cells used by a Turing machine, as a function of input length .
- The input tape is read-only and not counted, which is what makes sublinear space () meaningful.
- is the class of languages decidable within work-tape space.
- A machine using space can run at most steps before it must repeat a configuration.
- This time bound gives , linking space back to time.
- The model sets up , , , Savitch's Theorem, and the Space Hierarchy Theorem.
Space complexity counts only the reusable work-tape cells a machine touches, deliberately excluding the read-only input, so that algorithms can legitimately use less memory than the size of the problem they solve.
The idea
Space complexity asks: as a function of input length , how many tape cells does a Turing machine need to visit before it halts? This is a fundamentally different question from time complexity, because tape cells can be overwritten and reused, while time steps cannot be "reused" — each step happens once. A machine that runs for steps might still use only cells of memory, revisiting and rewriting the same small region over and over. This is precisely the phenomenon complexity theory wants to isolate and measure. To make sublinear space meaningful, we adopt a specific machine model: a multi-tape Turing machine with a read-only input tape and one or more separate, read-write work tapes. The input tape's head can move but can never write; the work tape is where all computation and storage happens, and it is the only tape whose usage counts toward the space bound. Without this separation, "space" would trivially be at least for any machine that has to read all input symbols, since in a single-tape model reading the input already uses cells. By quarantining the input on its own read-only tape, we allow the interesting resource — genuine working memory — to be smaller than the input itself, all the way down to in useful cases. Formally, for a function , we define the space complexity of a Turing machine that halts on all inputs as the function the maximum number of work-tape cells visits, maximized over all inputs of length . The class
collects all languages decidable within that space bound. This is the direct analogue of from Measuring Time Complexity, with "steps" replaced by "distinct cells visited on the work tape." The nondeterministic analogue is defined the same way but for nondeterministic Turing machines, where we require every branch of the computation to respect the space bound (equivalently, since we only care about accepting/rejecting behavior, that the machine never uses more than cells on any branch it explores before halting).
How it works
The machine model, precisely. A space-bounded Turing machine has:
- a read-only input tape holding the input string of length , bracketed by endmarkers, with a head that moves left/right but never writes;
- one or more read-write work tapes, initially blank, where performs all its computation;
- a finite control with states, exactly as in an ordinary Turing machine.
The space used on a given input is the number of distinct cells on the work tape(s) that the head ever visits during the run (for multiple work tapes, sum the cells used across tapes, or equivalently track the largest single tape needed and lose only a constant factor). We define
and say runs in space . As with time complexity, we use big- to suppress model-dependent constants: is the set of languages decided by some machine using space on inputs of length .
Why the read-only input tape is essential. Consider a machine that must merely check parity of the number of 1s in a bit string of length . On a single-tape machine, the head has already swept across all input cells — under a model where "space" means "cells visited, period," this machine trivially uses space no matter how clever it is, because reading the input costs . By moving the input onto a separate tape that is not counted, the same algorithm — sweep once, keep a single bit "parity so far" on the work tape — is revealed to use only space. This is the entire point of the convention: it isolates genuine working memory from the unavoidable cost of reading the problem statement.
A configuration and why space bounds control everything. A configuration of a space-bounded machine records: the current state, the position of the input head, the entire contents of all work tapes, and the positions of all work-tape heads. This is exactly analogous to a configuration in the time-complexity setting, but now the crucial fact is: > If a machine uses at most work-tape space, the number of distinct configurations is bounded — and if a machine ever revisits the same configuration twice, it is in an infinite loop. This single observation is the engine behind almost every theorem about space complexity, including the time bound derived below and (later) Savitch's Theorem and the Space Hierarchy Theorem.
Counting configurations. Suppose has states, work-tape alphabet size , uses at most cells on one work tape, and the input has length (so the input head has possible positions, or counting endmarkers). Then the number of distinct configurations is at most
since we choose a state ( ways), an input-head position ( ways), work-tape contents ( ways), and a work-tape head position ( ways). Because this is finite, a deciding machine that never repeats a configuration must halt within this many steps — otherwise, by pigeonhole, it would revisit a configuration and loop forever, contradicting the assumption that it halts on every input. ``` // Pseudocode: the space-complexity accounting used to derive // the time bound for an f(n)-space-bounded machine M. function ConfigurationBound(Q, Gamma, n, f_n): // number of possible states states = |Q| // number of positions for the read-only input head input_pos = n + 2 // includes both endmarkers // number of possible contents of the work tape (length f_n) tape_content = |Gamma| ^ f_n // number of positions for the work-tape head tape_pos = f_n return states input_pos tape_content * tape_pos // Consequence used throughout space-complexity theory: // If M halts on every input, then on inputs of length n, // M runs in at most ConfigurationBound(Q, Gamma, n, f(n)) steps, // because repeating a configuration would force an infinite loop. ``` ``` // Pseudocode: generic template for a space-bounded decider, // illustrating what "space used" means operationally. function DecideWithBoundedSpace(w): n = length(w) input_head = 0 // read-only, moves over w only work_tape = [] // read-write, grows only as touched state = q_start while state not in {q_accept, q_reject}: input_symbol = w[input_head] // read-only access work_symbol = read(work_tape, work_head) (state, new_work_symbol, move_input, move_work) = transition(state, input_symbol, work_symbol) write(work_tape, work_head, new_work_symbol) input_head += move_input // -1, 0, or +1 work_head += move_work // -1, 0, or +1 // SPACE USED so far = number of distinct work_head // positions visited; input_head movement is NOT counted. return (state == q_accept) ```
Complexity & correctness
Space usage is well-defined and monotone in the right sense. Because is required to halt on every input (we only define space complexity for deciders, exactly as with time complexity), the maximum in is a well-defined finite number for each : every computation on a fixed input is finite, so it visits finitely many cells, and there are finitely many inputs of length .
The fundamental space-to-time bound. This is the central quantitative fact of the theory: > Claim. If decides a language in space, with , then runs in time. Proof sketch. From the configuration count above, the number of distinct configurations reachable on an input of length is at most
Since (a standard convention that avoids degenerate sub-logarithmic cases), the factor , so every polynomial factor in and is absorbed into . Hence . Because halts on every input, it can never revisit the same configuration — if it did, it would repeat that configuration's entire future forever, contradicting halting. So the number of steps before halting is at most the number of distinct configurations, giving a running time of . This proves the inclusion
which is the space-complexity analogue of the trivial time-hierarchy fact that more time gives strictly more power — except here it runs the other direction, bounding time by space. It is the technical seed from which the containment and, ultimately, statements like are grown.
Time bounds space, too — but weakly. In the reverse direction, if runs in time, it visits at most work-tape cells (it can write to at most one new cell per step), so
Combined with the bound above this gives — a coarse but honest sandwich showing space is a strictly weaker resource in the sense that "small space" can hide "large time," but not vice versa.
Sublinear space is meaningful precisely because of the read-only convention. With input read-only, the classes of real interest emerge:
and (foreshadowed here, developed fully elsewhere) capture problems solvable with only logarithmically many work cells — enough to store a constant number of pointers into the input, but not enough to copy the input itself. This is only a coherent idea because the input tape does not count; if it did, space would be impossible for any machine that must inspect all symbols.
Correctness of the model itself. The "correctness" claim to verify here is that the definitions compose sensibly: (1) space usage does not depend on which of two "reasonable" multi-tape encodings we pick, up to a constant factor, exactly as with time complexity's linear speedup theorem, and (2) closure under complement is free for space classes in a way it is not (known to be) for time classes — flipping accept/reject states, or in the nondeterministic case appealing to the (deferred) Immerman–Szelepcsényi theorem, preserves the space bound exactly, since no extra memory is needed to swap accept and reject. These structural facts are what make space complexity, despite looking like a minor variant of time complexity, behave quite differently — a difference that becomes sharp with Savitch's Theorem.
Honest tradeoffs. The model is powerful precisely because it under-counts a real cost: a machine using space still spends time proportional to at least just moving its input head across the input, and typically far more (often polynomial, sometimes exponential, per the bound above) doing its computation. "Low space" is not "fast" — it is a genuinely different axis, and the entire point of this article is to keep that axis cleanly separated from time.
Worked example
Consider the language
strings that read the same forwards and backwards. We build a machine using only space — sublinear, since the input itself has length — by keeping just two pointers (indices) into the input on the work tape, rather than copying any of the input. ``` function IsPalindrome(w): // w given on read-only input tape, length n i = 0 // left pointer, stored on work tape in binary j = n - 1 // right pointer, stored on work tape in binary while i < j: a = w[i] // move input head to position i, read symbol b = w[j] // move input head to position j, read symbol if a != b: reject i = i + 1 j = j - 1 accept ```
Why this uses only space. The only information stored on the work tape is the pair of pointers and , each an integer between and . Writing an integer up to in binary takes bits, so storing both pointers takes work-tape cells — nothing else is ever written. The input itself is never copied; the machine repositions its (uncounted) input-tape head to whatever position or currently names, reads one symbol, and discards it. Let us trace this on reversed appropriately — take (), which is a palindrome, and , which is not.
| Step | (binary, work tape) | (binary, work tape) | Action | ||
|---|---|---|---|---|---|
| 0 | `000` (0) | `101` (5) | `1` | `1` | match, continue |
| 1 | `001` (1) | `100` (4) | `1` | `1` | match, continue |
| 2 | `010` (2) | `011` (3) | `0` | `0` | match, continue |
| 3 | `010`=`011`? no, : loop test fails | — | — | — | accept |
Work-tape contents used across the whole run: only the six bit-triples needed to represent and — at most bits total, i.e. , regardless of how large grows (the constant 6 would grow only logarithmically with ). Now trace the non-palindrome ():
| Step | Action | ||||
|---|---|---|---|---|---|
| 0 | 0 | 5 | `1` | `0` | mismatch → reject |
The machine halts immediately at step 0 with a reject, having used the same -bit budget for the pointers, confirming that the space bound does not depend on whether the string happens to be a palindrome — it is a worst-case guarantee, the way it must be for the definition of to make sense.
Contrast with time. This algorithm runs in time (it makes comparisons, each requiring the input head to reposition, costing up to moves per repositioning in the worst tape layout — so time here is in the crudest analysis, or with a smarter dual-head implementation). The point of the example is not to optimize time but to demonstrate: a language that visibly requires reading all input symbols can still be decided using only work-tape space, which is the entire content of the read-only-input convention.
Common pitfalls & traps
| Pitfall | Why it happens | Fix |
|---|---|---|
| Counting the input tape toward space | Habit from single-tape time-complexity models where "space" and "tape used" are conflated | Always use the two-tape convention: input read-only and uncounted, work tape counted |
| Forgetting the convention | Sub-logarithmic space cannot even store a pointer to the input head's own position | State space bounds as unless working in specialized sub-log models |
| Confusing "low space" with "fast" | Space and time feel like they should move together, since both are "resources" | Remember : low space can still mean huge time |
| Double-counting multiple work tapes additively when the definition asks for the max, or vice versa | Ambiguity in whether "space" sums tapes or takes the largest | Either convention changes complexity only by a constant factor for a fixed number of tapes; state which you use |
| Assuming nondeterministic space bounds every branch loosely | Treating like 's "some branch" intuition | Every branch of an computation must individually respect the bound |
| Ignoring that must halt on all inputs to define space complexity | Borrowing sloppy language from general TMs that may loop | Space complexity, like time complexity, is only defined for deciders (or machines guaranteed to halt) |
Pioneers & history
The formal study of space as a resource distinct from time grew out of the same 1960s program that gave rise to time-complexity classes, but its most distinctive results — the relationship between deterministic and nondeterministic space, and the space hierarchy — came slightly later and required new proof techniques specific to the reusability of memory.
Origins · 1 minJuris Hartmanis and how this was discovered
Hartmanis, working with Stearns at General Electric and later at Cornell, wrote the 1965 paper "On the Computational Complexity of Algorithms," which first formalized measuring resources like time and space as functions of input length and proved that more resources provably allow deciding more languages. This paper is the direct ancestor of the space-complexity framework used throughout this article, including the very idea of a hierarchy of classes.
Stearns co-authored the foundational hierarchy theorems with Hartmanis, establishing the mathematical machinery — diagonalization against space-bounded machines — that later underlies the Space Hierarchy Theorem. Their joint Turing Award recognized the creation of computational complexity theory as an independent field.
Where this matters
Space complexity is not an abstract nicety; it directly governs how algorithms are designed for real constrained hardware. Streaming algorithms, which process massive data sets (network traffic, log files, sensor streams) using memory far smaller than the stream length, are precisely -space algorithms in this formal sense — the read-only "input tape" is the incoming stream that cannot be stored, and the work tape is the small sketch or counter maintained in RAM. Embedded and IoT systems, with kilobytes of RAM but the need to process much larger inputs (firmware images, sensor logs), rely on the same discipline of bounding reusable memory independent of input size. Inside compilers and static analyzers, algorithms for graph reachability and dataflow analysis are often designed with an eye toward -style logarithmic-space bounds, since these translate to extremely memory-efficient implementations even on graphs with millions of nodes. The theoretical class captures the resource needs of solving fully quantified boolean formulas and many two-player games (generalized versions of games like Hex or Go), explaining why optimal game-tree search for such games is believed to require polynomial space but not polynomial time. Database query optimizers and model checkers used in hardware verification both operate under explicit space budgets that trace back to exactly this model: a large, read-only representation of state or schema, and a small, actively-managed work area — the same read-only-input, read-write-work-tape split introduced here. Understanding this split is the prerequisite for the next layer of the theory: L and NL as the logarithmic-space classes, Savitch's Theorem connecting deterministic and nondeterministic space, and PSPACE together with the Space Hierarchy Theorem that shows space, like time, forms a strict, infinite hierarchy of computational power.
Ask the tutor: How does Savitch's Theorem use the configuration-counting idea from this article to simulate nondeterministic space deterministically with only a quadratic blowup?
Why can't we just use a single tape and call the number of cells visited the "space complexity"?
On a single tape holding both input and working data, merely reading an input of length requires visiting at least cells, so no machine could ever use less than space regardless of how cleverly it computes. This would make sublinear space bounds like impossible for any language depending on all input symbols, collapsing important classes such as and into triviality. By separating a read-only input tape (uncounted) from a read-write work tape (counted), the model isolates genuine "thinking memory" from the unavoidable cost of reading the problem, which is exactly the resource we want to study. This convention is standard across every rigorous treatment of space complexity.
Does the linear speedup theorem for time complexity have an analogue for space?
Yes — space complexity enjoys an even stronger compression result than time's linear speedup. Because a work tape can encode several symbols per cell using a larger tape alphabet, a machine using space can be simulated by another machine using space for arbitrarily small constant , provided grows at least logarithmically. This means constant factors in space bounds are essentially meaningless, exactly as with time, and justifies the standard practice of writing space bounds only up to , e.g. rather than worrying about the exact constant.
Is nondeterministic space complexity defined the same way as nondeterministic time complexity?
The definitions look similar but the requirement is stricter for space. For , we only require that some accepting branch runs in steps when the input is in the language. For , we require that every branch the machine explores, whether or not it leads to acceptance, uses at most space — space is a bound on the machine's behavior at every point of every computation path, not just on the lucky accepting path. This distinction matters when later proving results like Savitch's Theorem, which crucially exploits this uniform space bound across all branches.
Why must we assume f(n) ≥ log n when discussing space complexity?
A machine needs at least bits of work-tape storage just to write down the position of its own input head, which is essential for almost any nontrivial computation involving the input, such as remembering where to resume reading. Sub-logarithmic space is studied in specialized settings (e.g., certain streaming or online models with restricted head movement), but the standard theory of , and results like the configuration-counting time bound, implicitly assume so the machine can at least index into the input. Without this convention, many basic theorems (including the space-to-time bound) require extra care or fail outright.
How does space complexity relate to the classes L, NL, and PSPACE mentioned but not developed here?
These classes are simply named special cases of the general framework: is everything decidable with logarithmic work-tape space, is its nondeterministic counterpart, and collects everything decidable in any polynomial amount of space. All three rely entirely on the read-only-input, read-write-work-tape model developed in this article; without that convention, none of them would be meaningfully distinct from classes defined by input size alone. Later results — Savitch's Theorem, the Immerman–Szelepcsényi theorem, and the Space Hierarchy Theorem — all manipulate exactly the configuration-counting and simulation techniques introduced here.
Can a problem be solvable in less time than the space it requires?
No — this is impossible under the standard model, and it follows directly from how a Turing machine operates. A machine can write to at most one new tape cell per computational step, so the number of distinct cells it can possibly visit is bounded above by the number of steps it takes; formally . This gives one direction of the sandwich relating time and space, while the configuration-counting argument gives the other direction (), together showing space is a resource that time can bound from below but not exceed arbitrarily.
What is the practical takeaway for someone designing an algorithm, not just studying theory?
If your algorithm needs to process an input far larger than available memory — a network stream, a massive log file, a huge on-disk graph — model the input as read-only and ask how small a work area (pointers, counters, a small hash table) suffices, exactly as this framework does. Many classic space-efficient techniques, such as reservoir sampling, two-pointer scanning, and streaming sketches (e.g., counting distinct elements approximately), are precisely instances of designing an -space Turing machine in this formal sense. Thinking in terms of "what must actually be stored versus what can be re-read from the input" is a transferable design discipline, not just an artifact of the theoretical model.