When to use an array
Use an array (or a string) when you need:
- Access by position: "the 5th item", "the last item", "item
i". It takes one step however long the array is. - To loop over everything in order, which is also the fastest way a computer can read data, because the items sit side by side in memory.
- A collection that mostly grows and shrinks at the end, such as a list of results or a stack of undo steps.
- A compact collection with no extra memory per item.
- Text: a string is an array of characters, so reading, slicing and scanning use the same ideas.
Use something else when:
- You look items up by a key, not a position: use a hash map.
- You add or remove at the front or middle all the time: use a linked list or a deque (double-ended queue).
- You need items kept in sorted order while they change: use a balanced tree.
- You only ask "is this in the set?": use a hash set.
Do not build arrays by hand. Every language has a growable array (see the real-world section). Writing one yourself is for learning and interviews.
How an array works
An array is a row of items stored side by side in memory, each in a numbered slot called an index, starting at 0.
An array's items are contiguous, so the address of item
iis the start of the array plusitimes the size of one item.
That sum is why reading any position takes one step. The cost is that the items must stay side by side, so putting one in the middle means shifting everything after it.
Two ideas to keep in mind:
- Fixed size or growable. A plain array has a fixed length. A dynamic array (Python
list, JavaArrayList, C++vector, Go slice, RustVec) reserves spare room, called its capacity. When it fills up it allocates a bigger array, usually a multiple of the old size, and copies everything across. - Strings are arrays of characters. In Java, Python, JavaScript, Go and C# a string cannot be changed in place: "changing" it builds a new string. In C++ and Rust you can edit a string.
A 2D array (a grid or matrix) is an array of rows, where each row is an array. Item (row, column) is grid[row][column]. An image, a spreadsheet and a chess board are all 2D arrays.
Try it
Start with 7 3 9 4. Try the operations and watch the items moved counter.
Array
Step 1 of 1 · Press Space to play, arrow keys to stepStart: an array holding 4 items with room for 4. Use the buttons above to try an operation.
- length:
- 4
- capacity:
- 4
- items moved:
- 0
- comparisons:
- 0
length = items stored. capacity = slots reserved. items moved counts every item copied or shifted.
Things to try:
- Append
5to the full array. It has to grow: the array doubles from 4 slots to 8 and copies 4 items. Then append6: no copy, no moves. - Insert
0at index0. All 4 items shift right, so 4 moves. Insert at the end instead and nothing moves. - Read index
2, then Search4. Reading by position is one step. Searching by value checks items one by one, here 4 comparisons. - Use the Letters start (
H E L L O) and delete index1to see how a string loses a character.
Array operations: read, search, insert and delete
Read by index. Jump straight to the slot. One step. This is the array's superpower.
Search by value. Without any order to rely on, check each item from the start until you find it, or reach the end. If the array is sorted, binary search is much faster (see the Sorting and Binary Search lesson).
Append. Put the item in the next free slot. If the array is full, allocate a bigger one and copy. Because the growth is a multiple (for example doubling), the average cost per append is O(1). This is called amortised O(1).
Insert in the middle. Move every item from that index onwards one place right, then place the new item. Cost grows with how many items sit after it.
Delete from the middle. Remove the item, then move every later item one place left to close the gap.
Strings. Because most strings are immutable, s = s + "x" in a loop copies the whole string each time, which is O(n²) overall. Collect the pieces in a list or a string builder and join them once at the end.
Interview fact. Reading by index is O(1), but insert and delete in the middle are O(n). A question that seems to ask for "insert" is often really asking whether you notice that shifting cost.
Array time complexity
| Operation | Normal case | Worst case |
|---|---|---|
| Read or write by index | O(1) | O(1) |
| Search by value (unsorted) | O(n) | O(n) |
| Append to a dynamic array | O(1) amortised | O(n) when it must grow |
| Insert at index | O(n) | O(n) |
| Delete at index | O(n) | O(n) |
| Memory | O(n) | O(n) |
The expensive cases come from shifting items or copying the whole array. Inserting or deleting at the end avoids shifting, and growing by a multiple keeps the copying rare.
Arrays vs other data structures
The right choice depends on what you do most. n is the number of items.
| What you need | Array | Linked list | Hash map | Sorted array |
|---|---|---|---|---|
Read item at position i | O(1) | O(n) | Not position-based | O(1) |
| Find a value | O(n) | O(n) | O(1) average | O(log n) |
| Add at the end | O(1) amortised | O(1) with a tail pointer | O(1) average | O(n) to keep order |
| Insert in the middle | O(n) | O(1) once you hold the node | Not position-based | O(n) |
| Delete from the middle | O(n) | O(1) once you hold the node | O(1) average by key | O(n) |
| Walk everything in order | O(n), fastest in practice | O(n), slower | No order | O(n), fastest in practice |
| Memory | O(n), compact | O(n) plus a pointer per item | O(n) plus spare slots | O(n), compact |
The bold cells show where each one wins. Arrays win on position and on scanning, because their items sit together in memory and the processor reads them quickly. They lose when you insert or delete away from the end.
How to explain arrays in an interview
- Say what an array is: "items side by side, so index
iis one step." - Give the costs in one breath: "read O(1), search O(n), insert and delete in the middle O(n), append O(1) amortised."
- Mention amortised growth: "it doubles when full, so the copy cost is spread across many appends."
- For strings, ask whether they are mutable in the language, and say you would use a builder for repeated concatenation.
- For a matrix, say the grid is
rows × columns, so a full pass is O(rows × columns).