一、题目

请实现一个简易内存池,根据请求命令完成内存分配和释放。

内存池支持两种操作命令REQUEST和RELEASE。其格式为:

REQUEST=请求的内存大小

表示请求分配指定大小内存。
如果分配成功,返回分配到的内存首地址;如果内存不足,或指定的大小为零则输出error

RELEASE=释放的内存首地址

表示释放掉之前分配的内存。释放成功无需输出;如果释放不存在的首地址则输出error

注意:

  1. 内存池总大小为100字节
  2. 内存池地址分配必须是连续内存,并优先从低地址分配
  3. 内存释放后可被再次分配,已释放的内存在空闲时不能被二次释放
  4. 不会释放已申请的内存块的中间地址
  5. 释放操作只是针对首地址所对应的单个内存块进行操作,不会影响其他内存块

二、输入

首行为整数N,表示操作命令的个数,取值范围0<N<=100

接下来的N行,每行将给出一个操作命令。操作命令和参数之间用”=“分割,输出描述见题目输出要求

三、输出

1
输出请求的内存块的首地址

四、示例

示例一

1
2
3
4
5
6
7
8
输入:
2
REQUEST=10
REQUEST=20

输出:
0
10

示例二

1
2
3
4
5
6
7
8
9
10
11
12
13
输入:
5
REQUEST=10
REQUEST=20
RELEASE=0
REQUEST=20
REQUEST=10

输出:
0
10
30
0

五、题解

  1. 注意题解中的 memory 不是真正分配的内存,可以理解为真实内存的逻辑地址,用来管理真正内存块
  2. 分配过的内存用 Map 来管理比较好理解;申请过的内存和释放的内存中通过标记数组来表示,让算法理解和实现起来更简单
  3. 网上还有一种解法是通过 Java 的 TreeMap 来管理分配过的内存块(key 为内存块起始地址,值为终地址)。方法比较高效,但是实现起来稍微有点技巧

5.1 Java 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package org.stone.study.algo.ex202411;

import java.util.*;

/**
* 简易内存池
*/
public class MemoryPool {

private final int[] memory;
private final Map<Integer, Integer> allocated;

public MemoryPool() {
this.memory = new int[100];
Arrays.fill(memory, 0);
this.allocated = new HashMap<>();
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
List<String> cmds = new ArrayList<>();
for (int i = 0; i < n; i++) {
cmds.add(sc.nextLine());
}

List<Object> res = new MemoryPool().execute(cmds);
res.forEach(System.out::println);
}

/**
* 执行引擎
* @param cmds
* @return
*/
public List<Object> execute(List<String> cmds) {
List<Object> res = new ArrayList<>();
for(String cmd : cmds) {
String[] cmdArr = cmd.split("=");
if("REQUEST".equals(cmdArr[0])) {
res.add(request(Integer.parseInt(cmdArr[1])));
} else if("RELEASE".equals(cmdArr[0])) {
Object errMsg = release(Integer.parseInt(cmdArr[1]));
if(errMsg != null) {
res.add(errMsg);
}
}
}

return res;
}

/**
* 申请内存
* @param size
* @return
*/
private Object request(int size) {
int start = 0;
if(size <= 0 || size > 100) {
return "error";
}

while(start < 100) {
// 找到连续的空闲内存起点
while (start < 100 && memory[start] != 0) {
start++;
}
if (start + size > 100) {
return "error";
}
// 找到连续的空闲内存终点
int end = start;
while (end < 100 && memory[end] == 0) {
++end;
}
// 找打一块连续的空闲内存
if (end - start >= size) {
allocated.put(start, size);
for (int i = start; i < start + size; i++) {
memory[i] = 1;
}
return start;
}
// 没有找到继续往后找连续内存
start = end;
}

return "error";
}

/**
* 释放内存
* @param address
* @return
*/
private Object release(int address) {
if(!allocated.containsKey(address)) {
return "error";
}

int size = allocated.get(address);
for(int i = address; i < address + size; i++) {
memory[i] = 0;
}

allocated.remove(address);

return null;
}
}

5.2 Python实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class MemoryPool:
def __init__(self, size):
self.size = size
self.memory = [0] * size
self.allocates = {}
def request(self, size):
if size <= 0 or size > self.size:
return 'error'

start = 0
while start < self.size:
# 找空闲内存起点
while start < self.size and self.memory[start] != 0:
start += 1
if start + size > self.size:
return 'error'
# 找空闲内存终点
end = start
while end < self.size and self.memory[end] == 0:
end += 1
# 如果找到空闲内存
if end - start >= size:
self.memory[start:start+size] = [1] * size
self.allocates[start] = size
return start

start = end

return 'error'

def release(self, address):
if address not in self.allocates:
return 'error'

size = self.allocates[address]
self.memory[address : address + size] = [0] * size
del self.allocates[address]

return None

def main():
# 5
n = int(input())
memoryPool = MemoryPool(100)

res = []
'''
REQUEST=10
REQUEST=20
RELEASE=0
REQUEST=20
REQUEST=10
'''
for _ in range(n):
op = input().split('=')
if op[0] == 'REQUEST':
size = int(op[1])
res.append(memoryPool.request(size))
elif op[0] == 'RELEASE':
address = int(op[1])
res.append(memoryPool.release(address))

'''
0
10
30
0
'''
for s in res:
if s != None:
print(s)

if __name__ == '__main__':
main()