Access is O(1)
Use index to jump directly to any element. No scanning needed.
An array is one of the most fundamental data structures in programming. Everything else - stacks, queues, trees, graphs - builds on top of this idea.
This guide covers arrays in Python (called lists), how memory works behind the scenes, and the time complexity of every operation.
An array is a collection where you store multiple values in one place, and each value has a numbered position called an index.
Think of it like a row of boxes, each box holding one value and having a number label on it.
Index: 0 1 2 3Value: [10] [20] [30] [40]You can reach any box instantly by its number - that is the superpower of arrays.
In Python, the built-in list is how you work with arrays.
A list is:
my_list = [1, 2, 3, 4]# Empty lista = []b = list()
# List with valuesnums = [10, 20, 30]mixed = [1, "hello", 3.5, True]
# Nested list (list inside a list)nested = [1, [2, 3], [4, 5]]Every element has an index. Python uses 0-based indexing - the first element is at index 0.
arr = [10, 20, 30, 40]
arr[0] # 10 (first element)arr[1] # 20arr[-1] # 40 (last element - negative index counts from end)arr[-2] # 30Forward: 0 1 2 3 [10] [20] [30] [40]Backward: -4 -3 -2 -1Slicing lets you grab a chunk of the list.
arr[start : end : step]start is included, end is NOT included.
arr = [10, 20, 30, 40, 50]
arr[1:3] # [20, 30] - index 1 and 2arr[:2] # [10, 20] - from start up to index 2arr[2:] # [30, 40, 50] - from index 2 to endarr[::2] # [10, 30, 50] - every second elementarr[::-1] # [50, 40, 30, 20, 10] - reversedLists are mutable, so you can change any element directly.
arr = [10, 20, 30]arr[1] = 99# arr is now [10, 99, 30]# append - add ONE element to the endarr.append(50)
# extend - add MULTIPLE elements to the endarr.extend([60, 70])
# insert - add at a specific positionarr.insert(1, 15) # insert 15 at index 1# remove - removes the FIRST occurrence of a valuearr.remove(20) # error if value not found
# pop - removes and RETURNS the elementx = arr.pop() # removes last elementy = arr.pop(1) # removes element at index 1
# clear - removes everythingarr.clear()arr.index(30) # returns the index of 30arr.count(10) # how many times 10 appearsarr.sort() # sort ascending, modifies originalarr.sort(reverse=True) # sort descending
new = sorted(arr) # returns NEW sorted list, original unchanged
arr.reverse() # reverses in placeThis is one of the most common bugs beginners write.
# WRONG - both a and b point to the same listb = a
# CORRECT - creates an independent copyb = a.copy()b = list(a)b = a[:]Why does the wrong way fail?
a --> [1, 2, 3]b --> same memory location
# Change b[0] and a[0] also changes!# Joining two listsa = [1, 2]b = [3, 4]c = a + b # [1, 2, 3, 4]
# Repeating a list[1, 2] * 3 # [1, 2, 1, 2, 1, 2]
# Checking membership10 in arr # True if 10 is in arr20 not in arr # True if 20 is NOT in arrarr = [10, 20, 30]
# Simple loopfor x in arr: print(x)
# Loop with indexfor i in range(len(arr)): print(i, arr[i])
# Loop with both index and value (cleanest)for i, x in enumerate(arr): print(i, x)List comprehension is a shorter way to build lists. Interviewers love it.
# Syntax[expression for item in iterable if condition]
# Squares of 0 to 4squares = [x * x for x in range(5)]# [0, 1, 4, 9, 16]
# Only even numberseven = [x for x in arr if x % 2 == 0]The same thing written as a regular loop:
result = []for x in arr: if x % 2 == 0: result.append(x)Both do the same thing. List comprehension is faster and cleaner.
len(arr) # number of elementsmax(arr) # largest valuemin(arr) # smallest valuesum(arr) # sum of all valuesA list can contain other lists. This is how you make a 2D grid or matrix.
matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix[0] # [1, 2, 3] - first rowmatrix[1][2] # 6 - row 1, column 2# WRONG - unpredictable behaviorfor x in arr: arr.remove(x)
# CORRECT - build a new listarr = [x for x in arr if x != value]This is important for theory/exam questions. Every array element sits in memory at a specific address.
LOC(A[i]) = BA + (i - L) * w| Symbol | Meaning |
|---|---|
BA | Base Address - where the array starts in memory |
L | Lower bound (usually 0 in Python, but can be different) |
i | Index of the element you want |
w | Size of one element in bytes |
Example: Array starts at address 100, element size = 4 bytes, lower bound = 0. Find address of index 3:
LOC(A[3]) = 100 + (3 - 0) * 4 = 100 + 12 = 112Most languages (C, Python) store 2D arrays row by row in memory.
LOC(A[i][j]) = BA + [(i - IL) * c + (j - JL)] * w| Symbol | Meaning |
|---|---|
BA | Base Address |
IL | Lower bound for rows |
JL | Lower bound for columns |
i | Row index |
j | Column index |
c | Total number of columns |
w | Element size in bytes |
Some languages (Fortran, MATLAB) store column by column.
LOC(A[i][j]) = BA + [(j - JL) * r + (i - IL)] * wWhere r = total number of rows.
This is what interviewers test you on.
| Operation | Time | Why |
|---|---|---|
Access by index arr[i] | O(1) | Direct memory jump using address formula |
| Append to end | O(1) | Adding at known position |
| Insert in middle | O(n) | All elements after must shift right |
| Delete from middle | O(n) | All elements after must shift left |
| Search (unsorted) | O(n) | May need to check every element |
| Sort | O(n log n) | Python uses TimSort |
len() | O(1) | Stored separately |
Python has an array module too. Here is the difference:
| Feature | List | array module |
|---|---|---|
| Data types | Mixed (int, str, float, etc.) | Same type only |
| Speed | Slightly slower | Faster for numbers |
| Usage | General purpose | Numeric-heavy work |
For DSA interviews, list is what you use. For heavy number crunching, NumPy arrays are even better.
Access is O(1)
Use index to jump directly to any element. No scanning needed.
Insert/Delete is O(n)
Middle insertions/deletions require shifting all elements after the point.
Copy carefully
Use .copy() or [:] - never b = a if you want a separate list.
List Comprehension
Faster and cleaner than a loop. Use it whenever building a new list from an old one.
Negative Indexing
arr[-1] is the last element. arr[-2] is second to last. Very useful in interviews.
Address Formula
LOC(A[i]) = BA + (i - L) * w. This is why index access is constant time.
.copy() or [:]append(), extend(), insert()remove(), pop(), clear()index(), count()sort(), sorted(), reverse().copy(), list(), [:]arr[::-1] to reversesorted() does not modify original; sort() does