开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情
设计内存分配器
给你一个整数 n ,表示下标从 0 开始的内存数组的大小。所有内存单元开始都是空闲的。
请你设计一个具备以下功能的内存分配器:
- 分配 一块大小为
size的连续空闲内存单元并赋 idmID。 - 释放 给定 id
mID对应的所有内存单元。
实现 Allocator 类:
Allocator(int n)使用一个大小为n的内存数组初始化Allocator对象。int allocate(int size, int mID)找出大小为size个连续空闲内存单元且位于 最左侧 的块,分配并赋 idmID。返回块的第一个下标。如果不存在这样的块,返回-1。int free(int mID)释放 idmID对应的所有内存单元。返回释放的内存单元数目。
提示:
1 <= n, size, mID <= 1000- 最多调用
allocate和free方法1000次
思路
首先很容易想到的是使用数组来储存内存的分配情况,数组的值存储内存的分配 ID。
需要分配内存时,从数组的 0 下标开始向后搜索,找到未被占用的内存空间,若可以存放相应长度的内存,就回到可分配的开始位置,将这一段内存标记为 mID。
在释放内存时,可以通过遍历一遍数组来实现,但我采取了另一种方法,使用 HashMap 存放对应 mID 的位置,在需要释放内存时,直接根据 HashMap 的映射找到相应位置,其中使用了 Pair 来存放内存标识的左右位置,将相应位置的标识置 0,最后在 HashMap 中删除该 mID。
题解
class Allocator {
private int n;
private int[] arr;
private Map<Integer, List<Pair<Integer, Integer>>> map;
public Allocator(int n) {
this.n = n;
arr = new int[n];
map = new HashMap<>();
}
public int allocate(int size, int mID) {
int left = 0;
boolean flag = true;
while(left + size <= n && flag) {
int right = left + size - 1;
for(int i = left; i <= right; i++) {
if(arr[i] != 0) {
left = i + 1;
break;
}else if(i == right) {
while(i >= left) {
arr[i--] = mID;
}
if(!map.containsKey(mID)) {
map.put(mID, new ArrayList<>());
}
List<Pair<Integer, Integer>> list = map.get(mID);
list.add(new Pair<>(left, right));
flag = false;
break;
}
}
}
return flag? -1: left;
}
public int free(int mID) {
if(!map.containsKey(mID)) {
return 0;
}
List<Pair<Integer, Integer>> list = map.get(mID);
int cnt = 0;
for(Pair<Integer, Integer> pair: list) {
int left = pair.getKey(), right = pair.getValue();
int index = left;
while(index <= right) {
arr[index++] = 0;
cnt++;
}
}
map.remove(mID);
return cnt;
}
}