Is the time-complexity of iterative string append actually On2, or On?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
The complexity of repeated string append depends on the data structure, not just the loop count. In immutable-string contexts, each append may copy earlier characters, which can push total work toward quadratic behavior. In mutable-buffer contexts, append is usually amortized linear over the final output size.
Why Immutable Strings Can Become Quadratic
An immutable string cannot be modified in place. If a loop runs n times and each step creates a new string from previous content plus new text, copy cost grows with current length.
Imagine appending one character per iteration. The first append copies about 1 character, the second copies about 2, and so on. Total copied characters are close to 1 + 2 + ... + n, which grows on the order of n^2.
Some runtimes apply optimizations for local concatenation, so real timings can be better than worst-case theory. Still, complexity analysis should assume no special optimization unless language documentation guarantees it.
Why Builders and Buffers Are Usually Linear
Mutable builders keep an internal array and expand capacity occasionally. Most appends write at current end without copying the full accumulated string. Resizing events copy data, but if growth factor is geometric, average append cost stays constant, and total cost for n appends is linear in output size.
The final toString usually performs one copy into an immutable String, which is expected and still keeps total work near linear.
Language-Specific Practical Patterns
Different languages have different idioms, but the principle stays the same.
Python
Use list accumulation and "".join(...) for many fragments.
JavaScript
For many small chunks, array plus join is often more predictable than repeated concatenation in hot loops.
Java
Prefer StringBuilder in loops. If multithreaded shared access is required, use StringBuffer or external synchronization.
Complexity Framing That Avoids Confusion
People often ask whether this is O(n) or O(n^2), but there are two different n definitions.
- If
nmeans number of append operations and each append adds fixed-size text, immutable naive append can trend quadratic. - If
nmeans final output length and you use a dynamic builder, total work is typically linear in that final length.
The disagreement usually comes from mixing these two interpretations.
Quick Benchmark Template
The simplest way to validate behavior on your runtime is to benchmark both approaches.
Benchmark on representative input sizes, not toy values, and run multiple rounds to reduce noise.
Common Pitfalls
- Declaring complexity without defining what
nmeans. - Assuming all runtimes optimize repeated concatenation identically.
- Benchmarking tiny strings and extrapolating to production scale.
- Ignoring memory pressure. Frequent intermediate string creation increases allocation and garbage collection overhead.
- Choosing thread-safe buffers by default when no sharing exists, adding unnecessary synchronization cost.
Summary
- Naive iterative append on immutable strings can approach quadratic total copy work.
- Mutable builders or chunk lists plus
joinusually provide amortized linear behavior. - Complexity debates often come from inconsistent definitions of
n. - Runtime optimizations may help, but builder-style patterns remain the safest default.
- Benchmark with realistic input sizes before locking in an implementation.
Related reading
- Is the time complexity of the empty algorithm O0?
- Is there a better way to guess possible unknown variables without brute force than I am doing? Machine learning?
- Is there a better way to guess possible unknown variables without brute force than I am doing? Machine learning?
- Is there a better way to guess possible unknown variables without brute force than I am doing? Machine learning?
- Is there a better way to trim a DateTime to a specific precision?
- Is there a decorator to simply cache function return values?
- Is there a Binary Search method in the C standard library?
- Is there a built-in Binary Search Tree in .NET 4.0?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.