Arrays store elements in contiguous memory. The address of any element
= base + index × sizeof(T).
This gives O(1) random access — the most efficient read in computing.
arr[3] = 8 accessed in O(1) — jump directly, no scanning needed.
vector<int> for dynamic arrays.
It wraps a heap-allocated array with automatic resizing (doubles when full → amortized O(1) push_back).
| Operation | Time | Space | Notes |
|---|---|---|---|
| arr[i] access | O(1) | O(1) | Direct address calculation |
| Linear search | O(n) | O(1) | Scan all elements |
| Binary search | O(log n) | O(1) | Requires sorted array |
| push_back | O(1)* | O(1) | Amortized — occasional resize |
| insert at index | O(n) | O(1) | Must shift all elements right |
| erase at index | O(n) | O(1) | Must shift all elements left |
1. Two Pointers
left & right converge from opposite ends. Converts O(n²) pair searches to O(n). Core pattern for 3Sum, Trapping Rain Water.
2. Prefix Sum
prefix[i] = sum(arr[0..i−1]). Any range sum [l,r] in O(1): prefix[r+1] − prefix[l]. Build once, query many times.
3. Sliding Window
Window grows right, shrinks left when constraint broken. Solves all contiguous subarray/substring problems in O(n).
4. Kadane's Algorithm
Maximum subarray in O(n). At each step: extend previous or start fresh. cur = max(num, cur + num).
Watch how inserting or deleting at a mid-index forces O(n) element shifts — and why arrays pay a cost for mid-mutations.
lo and hi walk inward, swapping each pair. Only O(n/2) swaps needed, O(1) extra space.
🧠 Under the Hood
All elements are contiguous in memory. The CPU can compute any element's address in a single multiply-and-add. The first 4 int elements fit in one cache line — iterating forwards is extremely cache-friendly, which is why arrays outperform linked lists for sequential reads even when they're the same O(n) complexity.