You are creating a new list object each time by concatenating. This requires copying all elements from the old list into a new one, plus one extra. So yes, using l = l + [i] is an O(N) algorithm, not O(1).

At the very least, don't use + concatenation; use += augmented concatenation, which is the same thing as list.extend() with a re-assignment to the same reference:

def test3():
    l = []
    for i in range(1000):
        l += [i]  # or use l.extend([i])
    return l

This produces:

>>> print timeit.repeat(stmt=test1, number=100, repeat=2)
[0.1333179473876953, 0.12804388999938965]
>>> print timeit.repeat(stmt=test2, number=100, repeat=2)
[0.01052403450012207, 0.007989168167114258]
>>> print timeit.repeat(stmt=test3, number=100, repeat=2)
[0.013209104537963867, 0.011193037033081055]
Answer from Martijn Pieters on Stack Overflow
🌐
Analytics Vidhya
analyticsvidhya.com › home › how to merge two lists in python?
How To Merge Two Lists in Python?
January 23, 2024 - Concatenated list using * operator: [‘apple’, ‘banana’, ‘orange’, ‘grape’, ‘watermelon’, ‘kiwi’] ... The time complexity of list concatenation using the * operator is O(n + m), where n and m are the lengths of the two ...
Discussions

algorithm - Complexity of creating list with concat operator in python - Stack Overflow
I am starting to learn about data structures+algorithms, and I have encountered an issue. Here is the function I am testing: def create_list_with_concat(n): l = [] for i in range(n): ... More on stackoverflow.com
🌐 stackoverflow.com
What is Python's list.append() method WORST Time Complexity? It can't be O(1), right?
I've read on Stackoverflow that in Python Array doubles in size when run of space It's actually not double, but it does increase proportional to the list size (IIRC it's about 12%, though there's some variance at smaller sizes). This does result in the same asymptotics though, so I'll assume doubling in the following description for simplicity. So basically it has to copy all addresses log(n) times. Not quite. Suppose we're appending n items to an empty vector. We will indeed do log(n) resizes, so you might think "Well, resizes are O(n), so log(n) resizes is n log(n) operations, which if we amortize over the n appends we did means n log(n)/n, or log(n) per append". However, there's a flaw in this analysis: we do not copy "all addresses" each of those times. Ie. the copies are not O(n). Sure, the last copy we do will involve copying n items, but the one before it only copied n/2, and so on. So we actually do 1 + 2 + 4 + ... + n copies, which sums to 2n-1. Divide that by n and you get ~2 operations per append - a constant. I assume since it copies addresses, not information We are indeed only copying the pointer, but this doesn't really matter for the complexity analysis. Even if it was copying a large structure, that'd only increase the time by a constant factor. Does that mean that O(1) is the average time complexity? It's the amortized worst case complexity (ie. what happens over a large number of operations). While any one operation can indeed end up doing O(n) operations, there's an important distinction that over a large number of operations, you are guaranteed to only be O(1), which is a distinction just talking about average case wouldn't capture. More on reddit.com
🌐 r/learnpython
11
3
October 26, 2022
python - Time complexity of appending a list to a list - Stack Overflow
I understand the amortized complexity of appending an element to a list is O(1) but what is the time complexity of appending a list to a list? For clarification: Appending an element to a list list... More on stackoverflow.com
🌐 stackoverflow.com
Runtime of merging two lists in Python - Stack Overflow
When you concatenate the two lists with A + B, you create a completely new list in memory. This means your guess is correct: the complexity is O(n + m) (where n and m are the lengths of the lists) since Python has to walk both lists in turn to build the new list. More on stackoverflow.com
🌐 stackoverflow.com
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-records-list-concatenation
Python | Records List Concatenation - GeeksforGeeks
April 13, 2023 - The original list 1 : [('g', 'f'), ... 'isbest'), ('best', 'st gfg')] Time complexity: O(n), where n is the length of the shorter list between test_list1 and test_list2....
🌐
YouTube
youtube.com › watch
Python list concatenation time complexity
To learn more, please visit the YouTube Help Center: https://www.youtube.com/help
🌐
Farmsfields
farmsfields.com › list-concatenation-python-time-complexity
List Concatenation Python Time Complexity
May 5, 2025 - Reason Each concatenation creates a new list and copies all existing elements repeatedly. ... Time Complexity O(k), linear with the total number of elements. Reason In-place modification avoids repeated copying of existing elements.
🌐
Runestone Academy
runestone.academy › ns › books › published › pythonds3 › AlgorithmAnalysis › Lists.html
2.6. Lists — Problem Solving with Algorithms and Data Structures 3rd edition
from timeit import Timer t1 = ... __main__ import test4") print(f"list range: {t4.timeit(number=1000):18.2f} milliseconds") concatenation: 6.54 milliseconds appending: 0.31 milliseconds list comprehension: 0.15 millis...
🌐
AlgoMonster
algo.monster › liteproblems › 1929
1929. Concatenation of Array - In-Depth Explanation
The time complexity is O(n), where n is the length of the array nums. The concatenation operation nums + nums in Python creates a new list by iterating through all elements of the first nums array and then all elements of the second nums array, resulting in 2n operations, which simplifies to O(n).
Top answer
1 of 3
11

The time complexity is not O(N)

The time complexity of the concat operation for two lists, A and B, is O(A + B). This is because you aren't adding to one list, but instead are creating a whole new list and populating it with elements from both A and B, requiring you to iterate through both.

Therefore, doing the operation l = l + [i] is O(len(l)), leaving you with N steps of doing an N operation, resulting in an overall complexity of O(N^2)

You are confusing concat with the append or extend function, which doesn't create a new list but adds to the original. If you used those functions, your time complexity would indeed be O(N)

An additional note:

The notation l = l + [i] can be confusing because intuitively it seems like [i] is simply being added to the existing l. This isn't true!

l + [i] builds a entirely new list and then has l point to that list.

On the other hand l += [i] modifies the original list and behaves like extend

2 of 3
3

Here is my thought process: I know that the concat operator is O(k) where k is the size of the list being added to the original list. Since the size of k is always 1 in this case because we are adding one character lists at a time, the concat operation takes 1 step.

This assumption is incorrect. If you write:

l + [i]

you construct a new list, this list will have m+1 elements, with m the number of elements in l, given a list is implemented like an array, we know that constructing such list will take O(m) time. We then assign the new list to l.

So that means that the total number of steps is:

 n
---
\              2
/    O(m) = O(n )
---
m=0

so the time complexity is O(n2).

You can however boost performance, by using l += [i], or even faster l.append(i), where the amortize cost is, for both l += [i] and l.append(i) O(1), so then the algorithm is O(n), the l.append(i) will however likely be a bit faster because we save on constructing a new list, etc.

Find elsewhere
🌐
Progressive Robot
progressiverobot.com › home › python › 6+ ways to concatenate lists in python
Lists: Complete Guide - Progressive Robot
May 12, 2026 - The following quick-and-dirty timeit snippet (run locally) demonstrates typical performance differences for large lists. Results will vary by machine and Python version, but the pattern is consistent: *Rule of thumb:* extend() tends to be fastest for in-place updates; + and * are competitive for producing new lists; chain() shines when you only need to iterate without materializing a new list. Each method of concatenating lists comes with trade-offs.
Price   $$
Address   Chester Business Park, 220 Heronsway, CH4 9GB
🌐
Codeforces
codeforces.com › blog › entry › 125610
Optimize Your Python Codeforces Solutions: Say Goodbye to str += str and Time Limit - Codeforces
When building strings iteratively, it's a common instinct to use the += operator to concatenate strings. However, what many Python developers may not realize is that this operation has a time complexity of approximately O(n^2).
🌐
Quora
quora.com › What-are-the-time-complexity-considerations-of-lists-in-Python
What are the time complexity considerations of lists in Python? - Quora
Answer: In a normal list on average: * Append : O(1) * Extend : O(k) - k is the length of the extension * Index : O(1) * Slice : O(k) * Sort : O(n log n) - n is the length of the list * Len : O(1) * Pop : O(1) - pop from end * Insert : O(n) - n is the length of the list * Del : O(n) - n...
🌐
w3reference
w3reference.com › blog › 6-ways-to-concatenate-lists-in-python
6+ Ways to Concatenate Lists in Python: A Comprehensive Guide — w3reference.com
The + operator is the most ... 2, 3, 4, 5, 6] Creates a new list (does not modify the original lists) Time complexity: O(n + m) where n and m are the lengths of the lists ·...
🌐
Reddit
reddit.com › r/learnpython › what is python's list.append() method worst time complexity? it can't be o(1), right?
r/learnpython on Reddit: What is Python's list.append() method WORST Time Complexity? It can't be O(1), right?
October 26, 2022 -

I know that lists in Python are implemented using arrays that store addresses to the information. Therefore, after several appends, when an array is loaded, it needs to reserve a new space and copy the entire array of addresses to the new place.

I've read on Stackoverflow that in Python Array doubles in size when run of space. So basically it has to copy all addresses log(n) times.

The bigger the list, the more copying it will need to do. So how can append operation have a Constant Time Complexity O(1) if it has some dependence on the array size

I assume since it copies addresses, not information, it shouldn't take long, python takes only 8 bytes for address after all. Moreover, it does so very rarely. Does that mean that O(1) is the average time complexity? Is my assumption right?

Top answer
1 of 4
4
I've read on Stackoverflow that in Python Array doubles in size when run of space It's actually not double, but it does increase proportional to the list size (IIRC it's about 12%, though there's some variance at smaller sizes). This does result in the same asymptotics though, so I'll assume doubling in the following description for simplicity. So basically it has to copy all addresses log(n) times. Not quite. Suppose we're appending n items to an empty vector. We will indeed do log(n) resizes, so you might think "Well, resizes are O(n), so log(n) resizes is n log(n) operations, which if we amortize over the n appends we did means n log(n)/n, or log(n) per append". However, there's a flaw in this analysis: we do not copy "all addresses" each of those times. Ie. the copies are not O(n). Sure, the last copy we do will involve copying n items, but the one before it only copied n/2, and so on. So we actually do 1 + 2 + 4 + ... + n copies, which sums to 2n-1. Divide that by n and you get ~2 operations per append - a constant. I assume since it copies addresses, not information We are indeed only copying the pointer, but this doesn't really matter for the complexity analysis. Even if it was copying a large structure, that'd only increase the time by a constant factor. Does that mean that O(1) is the average time complexity? It's the amortized worst case complexity (ie. what happens over a large number of operations). While any one operation can indeed end up doing O(n) operations, there's an important distinction that over a large number of operations, you are guaranteed to only be O(1), which is a distinction just talking about average case wouldn't capture.
2 of 4
2
Personally, I thought that lists worked as double LinkedLists, so insert time was O(1) But if it works as a dynamic array, time complexity should be amortized time, ie, close to O(1) but not quite
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-concatenate-n-consecutive-elements-in-string-list
Python | Concatenate N consecutive elements in String list - GeeksforGeeks
April 13, 2023 - Time complexity: O(n) Where n is the length of the input list test_list. In each recursive call, we slice the input list into two parts, which takes O(n) time in the worst case. We then make one recursive call with the second part of the list, ...
🌐
Plain English
plainenglish.io › home › blog › python › how to efficiently concatenate strings in python
How To Efficiently Concatenate Strings In Python
November 24, 2020 - The reason for this is, on every “+” operation a new string is created(Remember strings are immutable?) every single time and the existing values have to be copied character by character. The time complexity of this operation is O(n²).
🌐
sqlpey
sqlpey.com › python › python-list-concatenation-techniques
Python List Concatenation Techniques: Performance and Syntax Comparison
October 29, 2025 - The built-in sum() function can ... 4, 5, 6] Performance Caveat: As noted by experts, this method performs pairwise addition, leading to quadratic time complexity ($O(n^2)$) for large lists because memory allocation occurs repeatedly at each summation step....
🌐
Codecademy
codecademy.com › article › how-to-concatenate-list-in-python
How to Concatenate Two Lists in Python: 6 Effective Methods | Codecademy
For large lists or repeated concatenation, + and extend() are the most efficient. Between them, extend() is typically more efficient than + because + creates new lists with each operation, which increases memory usage and time complexity. Yes, Python lists can hold mixed data types.
Top answer
1 of 3
15

When you concatenate the two lists with A + B, you create a completely new list in memory. This means your guess is correct: the complexity is O(n + m) (where n and m are the lengths of the lists) since Python has to walk both lists in turn to build the new list.

You can see this happening in the list_concat function in the source code for Python lists:

static PyObject *
list_concat(PyListObject *a, PyObject *bb)
{
/* ...code snipped... */
    src = a->ob_item;
    dest = np->ob_item;
    for (i = 0; i < Py_SIZE(a); i++) {     /* walking list a */
        PyObject *v = src[i];
        Py_INCREF(v);
        dest[i] = v;
    }
    src = b->ob_item;
    dest = np->ob_item + Py_SIZE(a);
    for (i = 0; i < Py_SIZE(b); i++) {     /* walking list b */
        PyObject *v = src[i];
        Py_INCREF(v);
        dest[i] = v;
    }
/* ...code snipped... */

If you don't need a new list in memory, it's often a good idea to take advantage of the fact that lists are mutable (and this is where Python is smart). Using A.extend(B) is O(m) in complexity meaning that you avoid the overhead of copying list a.

The complexity of various list operations are listed here on the Python wiki.

2 of 3
2

My first guess is O(n+m), not sure if Python is smarter than that.

Nothing can be smarter than that while returning a copy. Though even if A, B were immutable sequences such as strings; CPython still makes a full copy instead of aliasing the same memory (it simplifies implementation of the garbage collection for such strings).

In some specific cases, the operation could be O(1) depending on what you want to do with the result e.g., itertools.chain(A, B) allows to iterate over all items (it does not make a copy, the change in A, B affects yielded items). Or if you need a random access; you could emulate it using a Sequence subclass e.g., WeightedPopulation but in the general case the copy and therefore O(n+m) runtime is unavoidable.

🌐
DigitalOcean
digitalocean.com › community › tutorials › concatenate-lists-python
6+ Ways to Concatenate Lists in Python | DigitalOcean
October 8, 2025 - However, note that using sum() for list concatenation is inefficient for large lists because it repeatedly creates new lists during the addition process, leading to quadratic time complexity.