Why Dynamic Arrays Double Their Size (ArrayList / std::vector)
🎯 The Question
"When a dynamic array (like Java
ArrayListor C++std::vector) runs out of capacity, why does it double its size ( geometric growth) instead of growing by a fixed amount (like or elements)?"
⚡ 30-Second Elevator Pitch
Arrays require contiguous physical memory. When an array is full and a new element is appended:
- The allocator cannot simply expand in place (adjacent RAM might be occupied).
- It must allocate a brand new, larger block of RAM elsewhere, copy all existing elements over, and free the old block.
- If size grew by elements (Fixed Growth): Inserting elements requires full memory copies, resulting in Quadratic Time—catastrophically slow.
- If size doubles ( Geometric Growth):
Resizing happens exponentially less often (). The total copies to insert items is:
This guarantees an Amortized Constant Time per
push_back().
🧠 Under-the-Hood: Geometric Resizing & Amortized
🔬 Mathematical Proof: Aggregate Method
To insert elements into a doubling array:
- Cost of inserting raw elements: writes.
- Cost of copying elements during resizes:
- Total Operations:
- Amortized Cost per Operation:
📌 Comparison Matrix: Fixed Growth vs. Geometric Growth
| Growth Strategy | Total Copy Work for Inserts | Amortized Cost per append() | Memory Waste Overhead |
|---|---|---|---|
| Fixed Increment () | 🐢 Linear | Minimal ( slots) | |
| Growth (Java / C++) | ⚡ Constant | Max 50% unused capacity | |
| Growth (MSVC / Folly) | ⚡ Constant | Max 33% unused capacity (Memory recycling friendly) |
💡 What Interviewers Ask Next (Follow-Up Traps)
-
"Why do some implementations (like MSVC
std::vectorand Facebook'sFBVector) use a growth factor instead of ?"- Answer: With a factor, the new allocated memory block is always strictly larger than the sum of all previously freed memory chunks (), preventing the memory allocator from reusing previously deallocated memory. A growth factor of (or the Golden Ratio ) allows the allocator to reuse previously freed memory segments, reducing fragmentation.
-
"How do you eliminate all reallocation overhead in production?"
- Answer: Call
reserve(expected_size)before inserting elements. This pre-allocates contiguous memory upfront, reducing resize operations and copying overhead to absolute zero.
- Answer: Call
Interview Answer: Dynamic arrays double their capacity because geometric progression ensures that the total number of element copies across insertions is bounded by . This mathematical property yields an amortized insertion time, whereas growing by a fixed constant incurs an copying penalty.