A static array has fixed size at creation (C/C++ int arr[10]). A dynamic array grows automatically when full (Python list, Java ArrayList, JavaScript array) — internally by allocating a bigger block, copying everything over, and freeing the old one.
Static: A parking lot with exactly 50 spots. When full, you're done. Dynamic: A restaurant that adds more tables when busy — it 'resizes' by moving to a bigger space and copying everything over.
Fixed size. Fast. Rigid. "Sorry, we're full."
Auto-resizes when full. "Hold on, getting a bigger box."
When Size == Capacity, the array creates a new larger block and copies everything. This is O(n), but happens rarely!
Fill the array — when it hits the limit, it copies and grows.
1// Python2my_list = []3my_list.append(1) # O(1)4my_list.append(2) # O(1)5# ... when internal array full:6# 1. Allocate 2x size7# 2. Copy all elements ← O(n)8# 3. Append new element9// Amortized: O(1) per append
Static Array (C/C++)
int arr[100];
That's it. 100 slots, forever. Want 101? Create a new array of 101, copy 100 elements, delete the old one. The programmer does this manually.
Dynamic Array (Python list, ArrayList, JS array)
You just append. When the backing array is full, the language quietly:
1. Allocates a new array (often 2× the size)
2. Copies all elements
3. Frees the old array
4. Adds your new element
So a single append is usually O(1), but occasionally O(n) when a resize happens. Averaged over many appends, it's O(1) per operation — we say amortized O(1).
The Tradeoff
Static arrays are fast and predictable but rigid. Dynamic arrays give flexibility — you don't need to guess the size upfront. Most modern languages use dynamic arrays by default. Understanding the resize cost (occasional O(n) copy) explains why appending is usually O(1) amortized.
"How does a dynamic array grow when full?"
It allocates a new bigger array, copies all elements, then frees the old one. Occasional O(n) cost.