Design Memory Allocator - Problem
Design and implement a dynamic memory allocator that manages a contiguous block of memory. Think of it like managing RAM in an operating system - you need to efficiently allocate blocks of memory to different processes and free them when they're no longer needed.
You're given an integer n representing the size of a 0-indexed memory array. Initially, all memory units are free (available for allocation).
Your memory allocator must support these operations:
- Allocate: Find the leftmost block of consecutive free memory units of a given size and assign it a memory ID (mID)
- Free: Release all memory units associated with a given memory ID
Key constraints:
- Multiple separate blocks can be allocated to the same mID
- When freeing memory, you must free ALL units with that mID, regardless of how they were allocated
- Always allocate to the leftmost available position to minimize fragmentation
Input & Output
basic_operations.py โ Python
$
Input:
["Allocator", "allocate", "allocate", "allocate", "freeMemory", "allocate", "allocate", "allocate", "freeMemory"]
[[10], [1, 1], [1, 2], [1, 3], [2], [3, 4], [1, 1], [1, 1], [1]]
โบ
Output:
[null, 0, 1, 2, 1, 3, 6, 7, 1]
๐ก Note:
Allocator(10) creates memory of size 10. allocate(1,1) finds leftmost free position 0. allocate(1,2) finds position 1. allocate(1,3) finds position 2. freeMemory(2) frees position 1, returns 1. allocate(3,4) finds positions 3-5, returns 3. allocate(1,1) finds position 1 (now free), returns 1. allocate(1,1) finds position 6, returns 6. freeMemory(1) frees positions 0,1,6, returns 3.
multiple_blocks_same_id.py โ Python
$
Input:
["Allocator", "allocate", "allocate", "allocate", "freeMemory"]
[[8], [2, 1], [2, 1], [2, 2], [1]]
โบ
Output:
[null, 0, 2, 4, 4]
๐ก Note:
Create memory of size 8. allocate(2,1) takes positions 0-1, returns 0. allocate(2,1) takes positions 2-3 for same mID, returns 2. allocate(2,2) takes positions 4-5, returns 4. freeMemory(1) frees ALL positions with mID 1 (both blocks: 0,1,2,3), returns 4.
allocation_failure.py โ Python
$
Input:
["Allocator", "allocate", "allocate", "allocate"]
[[5], [3, 1], [3, 2], [2, 3]]
โบ
Output:
[null, 0, -1, 3]
๐ก Note:
Create memory of size 5. allocate(3,1) takes positions 0-2, returns 0. allocate(3,2) cannot find 3 consecutive free positions, returns -1. allocate(2,3) finds positions 3-4, returns 3.
Visualization
Tap to expand
Understanding the Visualization
1
Initialize Memory
Start with empty memory array where 0 = free, mID = allocated
2
Allocate Memory
Scan from left to find first fit, mark positions with mID, track in hash map
3
Multiple Allocations
Same mID can have multiple separate blocks, all tracked together
4
Free Memory
Use hash map to instantly find and free all positions for an mID
Key Takeaway
๐ฏ Key Insight: Combining array simulation with hash map tracking gives us the best of both worlds - efficient memory state management and fast freeing operations.
Time & Space Complexity
Time Complexity
O(n)
Allocation scans up to n positions, freeing takes O(k) where k is number of units to free
โ Linear Growth
Space Complexity
O(n + m)
Memory array O(n) plus hash map storing up to n positions across m different mIDs
โก Linearithmic Space
Constraints
- 1 โค n, size โค 1000
- 1 โค mID โค 1000
- At most 1000 calls will be made to allocate and freeMemory
- Memory positions are 0-indexed
๐ก
Explanation
AI Ready
๐ก Suggestion
Tab
to accept
Esc
to dismiss
// Output will appear here after running code