Learn how dynamic arrays achieve O(1) amortized insertion, contiguous memory layout, and geometric doubling strategies.
Master the converging two pointers technique to solve pair sum, palindrome verification, and partition problems in O(N) linear time.
A static array reserves a fixed block of sequential memory addresses at allocation time. A Dynamic Array (like JavaScript Arrays or Python Lists) expands automatically as new elements are added.
When a dynamic array reaches maximum capacity, it cannot simply expand in-place because adjacent memory might be occupied. Instead:
Initial Capacity [4]: [ 10 | 20 | 30 | 40 ] (FULL)
│
Doubling Allocation (Capacity 8)
▼
New Block: [ 10 | 20 | 30 | 40 | 50 | __ | __ | __ ]
▲──────────────▲ ▲
Copied Items New Item
Copying $N$ elements takes $O(N)$ time, but resizing happens rarely (only after $1, 2, 4, 8, 16, dots$ elements). Averaged across $N$ insertions, the cost per push operation is $O(1)$ amortized.
| Operation | Time Complexity | Note |
|---|---|---|
Index Access arr[i] | $O(1)$ | Direct pointer arithmetic calculation |
| Append / Push | $O(1)$ Amortized | Occasional $O(N)$ reallocation |
| Insert / Remove at Start | $O(N)$ | Requires shifting all $N$ elements right or left |
arr.unshift() or arr.shift() in a loop turns an $O(N)$ algorithm into an accidental $O(N^2)$ bottleneck because every shift re-indexes all elements. Use two pointers or queues instead.Understand array memory layouts to avoid hidden re-indexing costs. Next, let's explore the Two Pointers Pattern!