Design Memory Allocator

Leetcode#2502

Problem Statement

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:

  1. Allocate a block of size consecutive free memory units and assign it the id mID.
  2. 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 an Allocator object with a memory array of size n.
  • int allocate(int size, int mID) Find the leftmost block of size consecutive free memory units and allocate it with the id mID. 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 id mID. Return the number of memory units you have freed.

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 1000 calls will be made to allocate and freeMemory.

Logic

  • The finding free slot work can be simplified using sliding window approach
  • Always start with sliding window logic for size of k and array is present in problem.
  • Use map for future free operations.

Golang code

/**
 * Your Allocator object will be instantiated and called as such:
 * obj := Constructor(n);
 * param_1 := obj.Allocate(size,mID);
 * param_2 := obj.FreeMemory(mID);
 */

type Allocator struct {
	arr           []int
	memoryMap     map[int][]int
	totalFreeSlot int
	totalSlot     int
}

func Constructor(n int) Allocator {
	return Allocator{
		arr:           make([]int, n),
		memoryMap:     make(map[int][]int),
		totalSlot:     n,
		totalFreeSlot: n,
	}
}

func (this *Allocator) Allocate(size int, mID int) int {
	if this.totalFreeSlot < size {
		return -1
	}

	start := -1
	freeSlotCounter := 0

  // sliding windows approach
  // keep it simple
	for i := 0; i < this.totalSlot; i++ {
		if this.arr[i] == 0 {
			if start == -1 {
				start = i
			}

			freeSlotCounter++
			if freeSlotCounter == size {
				// allocate memory for mID

				for j := start; j < start+size; j++ {
					this.arr[j] = mID
					this.memoryMap[mID] = append(this.memoryMap[mID], j)
				}
				this.totalFreeSlot -= size
				return start
			}
		} else {
			start = -1
			freeSlotCounter = 0
		}
	}
	return -1
}

func (this *Allocator) FreeMemory(mID int) int {
	freedMemory := 0
	if values, exist := this.memoryMap[mID]; exist {
		// reset the memory units
		for _, value := range values {
			this.arr[value] = 0
		}
		freedMemory = len(values)

		// update free slot counter
		this.totalFreeSlot += freedMemory

		// free up the memory
		delete(this.memoryMap, mID)
	}

	return freedMemory
}

Output

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]

Please visit https: https://codeandalgo.com for more such contents.

Leave a Reply

Your email address will not be published. Required fields are marked *