Design Memory Allocator
MediumUpdated: Aug 2, 2025
Practice on:
Problem
You are given an integer n representing the size of a 0-indexed memory array. All memory units are initially free.
You have a memory allocator with the following functionalities:
- Allocate a block of
sizeconsecutive free memory units and assign it the idmID. - Free all memory units with the given id
mID.
Note that:
- Multiple blocks can be allocated to the same
mID. - You should free all the memory units with
mID, even if they were allocated in different blocks.
Implement the Allocator class:
Allocator(int n)Initializes anAllocatorobject with a memory array of sizen.int allocate(int size, int mID)Find the leftmost block ofsizeconsecutive free memory units and allocate it with the idmID. Return the block's first index. If such a block does not exist, return-1.int freeMemory(int mID)Free all memory units with the idmID. Return the number of memory units you have freed.
Examples
Example 1
**Input**
["Allocator", "allocate", "allocate", "allocate", "freeMemory", "allocate", "allocate", "allocate", "freeMemory", "allocate", "freeMemory"]
[[10], [1, 1], [1, 2], [1, 3], [2], [3, 4], [1, 1], [1, 1], [1], [10, 2], [7]]
**Output**
[null, 0, 1, 2, 1, 3, 1, 6, 3, -1, 0]
**Explanation**
Allocator loc = new Allocator(10); // Initialize a memory array of size 10. All memory units are initially free.
loc.allocate(1, 1); // The leftmost block's first index is 0. The memory array becomes [**1** ,_,_,_,_,_,_,_,_,_]. We return 0.
loc.allocate(1, 2); // The leftmost block's first index is 1. The memory array becomes [1,**2** ,_,_,_,_,_,_,_,_]. We return 1.
loc.allocate(1, 3); // The leftmost block's first index is 2. The memory array becomes [1,2,**3** ,_,_,_,_,_,_,_]. We return 2.
loc.freeMemory(2); // Free all memory units with mID 2. The memory array becomes [1,_, 3,_,_,_,_,_,_,_]. We return 1 since there is only 1 unit with mID 2.
loc.allocate(3, 4); // The leftmost block's first index is 3. The memory array becomes [1,_,3,**4** ,**4** ,**4** ,_,_,_,_]. We return 3.
loc.allocate(1, 1); // The leftmost block's first index is 1. The memory array becomes [1,**1** ,3,4,4,4,_,_,_,_]. We return 1.
loc.allocate(1, 1); // The leftmost block's first index is 6. The memory array becomes [1,1,3,4,4,4,**1** ,_,_,_]. We return 6.
loc.freeMemory(1); // Free all memory units with mID 1. The memory array becomes [_,_,3,4,4,4,_,_,_,_]. We return 3 since there are 3 units with mID 1.
loc.allocate(10, 2); // We can not find any free block with 10 consecutive free memory units, so we return -1.
loc.freeMemory(7); // Free all memory units with mID 7. The memory array remains the same since there is no memory unit with mID 7. We return 0.
Constraints
1 <= n, size, mID <= 1000- At most
1000calls will be made toallocateandfreeMemory.
Solution
Method 1 – Linear Scan with Array
Intuition
We can use a simple array to represent the memory, where each cell stores the mID or 0 for free. To allocate, scan for the leftmost block of consecutive free cells. To free, scan and reset all cells with the given mID.
Approach
- Use an array
memof sizen, initialized to 0 (free). - For
allocate(size, mID), scan from left to right for the first block ofsizeconsecutive 0s. If found, set those cells tomIDand return the start index; else return -1. - For
freeMemory(mID), scan the array and set all cells with valuemIDto 0, counting the number of cells freed. Return the count.
Code
C++
class Allocator {
vector<int> mem;
public:
Allocator(int n) : mem(n, 0) {}
int allocate(int size, int mID) {
for (int i = 0; i + size <= mem.size(); ++i) {
bool ok = true;
for (int j = 0; j < size; ++j) if (mem[i+j]) { ok = false; break; }
if (ok) {
for (int j = 0; j < size; ++j) mem[i+j] = mID;
return i;
}
}
return -1;
}
int freeMemory(int mID) {
int cnt = 0;
for (int& x : mem) if (x == mID) { x = 0; cnt++; }
return cnt;
}
};
Go
type Allocator struct {
mem []int
}
func Constructor(n int) Allocator {
return Allocator{mem: make([]int, n)}
}
func (a *Allocator) Allocate(size, mID int) int {
for i := 0; i+size <= len(a.mem); i++ {
ok := true
for j := 0; j < size; j++ {
if a.mem[i+j] != 0 {
ok = false
break
}
}
if ok {
for j := 0; j < size; j++ {
a.mem[i+j] = mID
}
return i
}
}
return -1
}
func (a *Allocator) FreeMemory(mID int) int {
cnt := 0
for i := range a.mem {
if a.mem[i] == mID {
a.mem[i] = 0
cnt++
}
}
return cnt
}
Java
public class Allocator {
private int[] mem;
public Allocator(int n) {
mem = new int[n];
}
public int allocate(int size, int mID) {
for (int i = 0; i + size <= mem.length; ++i) {
boolean ok = true;
for (int j = 0; j < size; ++j) if (mem[i+j] != 0) { ok = false; break; }
if (ok) {
for (int j = 0; j < size; ++j) mem[i+j] = mID;
return i;
}
}
return -1;
}
public int freeMemory(int mID) {
int cnt = 0;
for (int i = 0; i < mem.length; ++i) if (mem[i] == mID) { mem[i] = 0; cnt++; }
return cnt;
}
}
Kotlin
class Allocator(n: Int) {
private val mem = IntArray(n)
fun allocate(size: Int, mID: Int): Int {
for (i in 0..mem.size - size) {
if ((0 until size).all { mem[i+it] == 0 }) {
for (j in 0 until size) mem[i+j] = mID
return i
}
}
return -1
}
fun freeMemory(mID: Int): Int {
var cnt = 0
for (i in mem.indices) if (mem[i] == mID) { mem[i] = 0; cnt++ }
return cnt
}
}
Python
class Allocator:
def __init__(self, n: int):
self.mem = [0] * n
def allocate(self, size: int, mID: int) -> int:
for i in range(len(self.mem) - size + 1):
if all(x == 0 for x in self.mem[i:i+size]):
for j in range(i, i+size):
self.mem[j] = mID
return i
return -1
def freeMemory(self, mID: int) -> int:
cnt = 0
for i in range(len(self.mem)):
if self.mem[i] == mID:
self.mem[i] = 0
cnt += 1
return cnt
Rust
struct Allocator {
mem: Vec<i32>,
}
impl Allocator {
fn new(n: i32) -> Self {
Self { mem: vec![0; n as usize] }
}
fn allocate(&mut self, size: i32, mID: i32) -> i32 {
let n = self.mem.len();
for i in 0..=n - size as usize {
if self.mem[i..i+size as usize].iter().all(|&x| x == 0) {
for j in i..i+size as usize {
self.mem[j] = mID;
}
return i as i32;
}
}
-1
}
fn free_memory(&mut self, mID: i32) -> i32 {
let mut cnt = 0;
for x in self.mem.iter_mut() {
if *x == mID {
*x = 0;
cnt += 1;
}
}
cnt
}
}
TypeScript
class Allocator {
private mem: number[];
constructor(n: number) {
this.mem = Array(n).fill(0);
}
allocate(size: number, mID: number): number {
for (let i = 0; i + size <= this.mem.length; ++i) {
if (this.mem.slice(i, i+size).every(x => x === 0)) {
for (let j = i; j < i+size; ++j) this.mem[j] = mID;
return i;
}
}
return -1;
}
freeMemory(mID: number): number {
let cnt = 0;
for (let i = 0; i < this.mem.length; ++i) {
if (this.mem[i] === mID) {
this.mem[i] = 0;
cnt++;
}
}
return cnt;
}
}
Complexity
- ⏰ Time complexity:
O(n*size)for allocate,O(n)for freeMemory, wherenis the memory size. - 🧺 Space complexity:
O(n), for the memory array.