Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Runtime of merging two lists in Python

Suppose we have two lists A = [a1, a2, ..., an](n elements), and B = [b1, b2, ..., bm](m elements), and we use "+" in Python to merge two lists into one, so

C = A + B;

My question is what the runtime of this operation is? My first guess is O(n+m), not sure if Python is smarter than that.

like image 289
Toby Avatar asked Mar 22 '15 17:03

Toby


People also ask

What is the time complexity of merging two lists?

Time Complexity: O(N+M) where N and M are the sizes of linked lists. Space Complexity: O(N+M), creating dummy nodes.

How do you merge two lists in Python?

In python, we can use the + operator to merge the contents of two lists into a new list. For example, We can use + operator to merge two lists i.e. It returned a new concatenated lists, which contains the contents of both list_1 and list_2.

What is runtime complexity of the list's built in append () method?

Time Complexity: Append has constant time complexity i.e.,O(1). Extend has a time complexity of O(k). Where k is the length of the list which need to be added.

What is the complexity of merging two lists with n items each using the two finger walking algorithm?

Therefore the overall complexity is O (m log n).


1 Answers

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.

like image 65
Alex Riley Avatar answered Sep 20 '22 18:09

Alex Riley