Intuition
Picture a row of numbered lockers. To open locker 500 you walk straight to it: you never open lockers 1 to 499 on the way. That’s an array. Because every slot is the same size and the slots sit side by side, the address of slot i is just start + i × slot size.
The catch is the same row. To fit a new item between lockers 2 and 3, everything from locker 3 on has to move down by one. (A linked list avoids the shifting, at the cost of fast indexing.)
How it works
- Reading or writing
a[i]: one calculation and one memory access, whatever the size. O(1) in Big O terms. - Inserting at index
i: shift every value from the end down toione place right, starting at the end so nothing is overwritten, then write the new value. O(n − i). - Deleting at index
i: shift the later values one place left. O(n − i). - Growing: a fixed array can’t. Dynamic arrays (Python lists, JavaScript arrays, Java’s
ArrayList, Go slices, Rust’sVec) allocate a bigger block, usually about double, and copy everything over. Because that happens rarely, adding at the end costs O(1) on average.
Common mistakes
- Off-by-one indexes. The last value of an n-item array is at
n - 1. - Shifting from the wrong end. Shifting right must start at the end; starting at the insert point copies one value over all the others.
- Inserting at the front in a loop. Each insert is O(n), so n of them is O(n²). Append and reverse once, or use a deque (see stacks and queues).
- Treating
list.insertorspliceas free. They hide the same shifting loop.
In other languages
| Language | Fixed size | Growable | Insert in the middle |
|---|---|---|---|
| Python | array.array (typed) |
list |
a.insert(i, x) |
| JavaScript | Typed arrays | Array |
a.splice(i, 0, x) |
| Java | int[] |
ArrayList |
list.add(i, x) |
| C | int a[n] |
Manual realloc |
Manual memmove |
| Go | [n]int |
Slices | slices.Insert(a, i, x) |
| Rust | [i32; N] |
Vec |
v.insert(i, x) |
Check yourself
Check yourself
Inserting at index 0 of an array holding 1,000 values moves how many values?
Every existing value shifts one place right to free index 0.
Check yourself
Reading a[500] from an array of 1,000 values takes…
The address is computed directly from the index, so reading any position is O(1).
Sources
- Cormen, Leiserson, Rivest and Stein, Introduction to Algorithms, section 17.4, “Dynamic tables” (3rd edition).
Finished this page?
Your list