#C0E46. 为OD机试E卷 - 内存资源分配
为OD机试E卷 - 内存资源分配
华为OD机试E卷 - 内存资源分配(Java & Python& JS & C++ & C )
https://blog.csdn.net/banxia_frontend/article/details/141951340
最新华为OD机试
题目描述
有一个简易内存池,内存按照大小粒度分类,每个粒度有若干个可用内存资源,用户会进行一系列内存申请,需要按需分配内存池中的资源返回申请结果成功失败列表。
分配规则如下:
- 分配的内存要大于等于内存的申请量,存在满足需求的内存就必须分配,优先分配粒度小的,但内存不能拆分使用;
- 需要按申请顺序分配,先申请的先分配,有可用内存分配则申请结果为true;
- 没有可用则返回false。
注意:不考虑内存释放
输入描述
输入为两行字符串
第一行为内存池资源列表,包含内存粒度数据信息,粒度数据间用逗号分割
- 一个粒度信息内用冒号分割,冒号前为内存粒度大小,冒号后为数量
- 资源列表不大于1024
- 每个粒度的数量不大于4096
第二行为申请列表,申请的内存大小间用逗号分割
- 申请列表不大于100000
如: 64:2,128:1,32:4,1:128 50,36,64,128,127
输出描述
输出为内存池分配结果
如true,true,true,false,false
示例1
输入
64:2,128:1,32:4,1:128
50,36,64,128,127
输出
true,true,true,false,false
说明
内存池资源包含:64K共2个、128K共1个、32K共4个、1K共128个的内存资源; 针对50,36,64,128,127的内存申请序列,分配的内存依次是:64,64,128,NULL,NULL, 第三次申请内存时已经将128分配出去,因此输出结果是: true,true,true,false,false
解题思路
规则总结:
- 按需分配内存,不能拆分。
- 优先分配最小的满足条件的内存块。
- 内存池中的资源一旦分配出去,就无法再次使用。
- 若没有可用内存块满足需求,返回
false
。
示例解释:
输入:
64:2,128:1,32:4,1:128
50,36,64,128,127
输出:
true,true,true,false,false
解释过程:
-
内存池初始化:
- 内存池资源为:
- 64K 的内存块有 2 个。
- 128K 的内存块有 1 个。
- 32K 的内存块有 4 个。
- 1K 的内存块有 128 个。
- 内存池资源为:
-
申请 50K 内存:
- 50K 需要一个大于等于 50K 的内存块。
- 从内存池中寻找,最小满足要求的内存块是 64K,因此分配一个 64K 的内存块,成功,返回
true
。 - 剩余内存池:64:1, 128:1, 32:4, 1:128。
-
申请 36K 内存:
- 36K 需要一个大于等于 36K 的内存块。
- 最小满足要求的内存块是 64K,因此分配一个 64K 的内存块,成功,返回
true
。 - 剩余内存池:64:0, 128:1, 32:4, 1:128。
-
申请 64K 内存:
- 64K 需要一个大于等于 64K 的内存块。
- 内存池中没有剩余的 64K 内存块,唯一满足条件的内存块是 128K,因此分配一个 128K 的内存块,成功,返回
true
。 - 剩余内存池:64:0, 128:0, 32:4, 1:128。
-
申请 128K 内存:
- 128K 需要一个大于等于 128K 的内存块。
- 但是内存池中已经没有 128K 或更大的内存块了,分配失败,返回
false
。
-
申请 127K 内存:
- 127K 需要一个大于等于 127K 的内存块。
- 同样,内存池中没有 128K 或更大的内存块,分配失败,返回
false
。
最终,输出为 true,true,true,false,false
。
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
// 处理输入
Scanner scanner = new Scanner(System.in);
String memoryInfo = scanner.next();
String applyList = scanner.next();
// 内存信息
List<Integer> memoryList = new ArrayList<>();
List<String> memoryInfoList = Arrays.asList(memoryInfo.split(","));
for (String info : memoryInfoList) {
int colonIndex = info.indexOf(":");
int size = Integer.parseInt(info.substring(0, colonIndex));
int count = Integer.parseInt(info.substring(colonIndex + 1));
for (int i = 0; i < count; i++) {
memoryList.add(size);
}
}
// 排序内存池,优先从小到大分配更精准的内存
Collections.sort(memoryList);
// 申请信息
List<Integer> applyMemoryList = new ArrayList<>();
List<String> applyListList = Arrays.asList(applyList.split(","));
for (String apply : applyListList) {
applyMemoryList.add(Integer.parseInt(apply));
}
// 分配内存
List<Boolean> resultList = new ArrayList<>();
for (int applyMemory : applyMemoryList) {
boolean flag = false; // 标志位:是否成功分配
for (int i = 0; i < memoryList.size(); i++) {
if (memoryList.get(i) >= applyMemory) {
flag = true;
memoryList.remove(i); // 分配内存后移除
break;
}
}
resultList.add(flag); // 记录分配结果
}
// 输出结果
for (int i = 0; i < resultList.size(); i++) {
System.out.print(resultList.get(i));
if (i != resultList.size() - 1) {
System.out.print(",");
}
}
}
}
Python
# 导入所需模块
from typing import List
# 主函数
def main():
# 处理输入
memory_info = input() # 输入内存池资源信息
apply_list = input() # 输入申请信息
# 内存信息
memory_list = [] # 创建一个列表存储内存池中的每个内存块
memory_info_list = memory_info.split(",") # 按逗号分割内存池信息
for info in memory_info_list: # 遍历每个内存块信息
colon_index = info.index(":") # 找到冒号的位置
size = int(info[:colon_index]) # 提取内存块大小
count = int(info[colon_index + 1:]) # 提取内存块数量
for _ in range(count): # 根据内存块数量添加到内存列表中
memory_list.append(size)
# 排序内存池,优先从小到大分配更精准的内存
memory_list.sort()
# 申请信息
apply_memory_list = list(map(int, apply_list.split(","))) # 将申请列表按逗号分割并转为整数
# 分配内存
result_list = [] # 存储每次申请是否成功的结果
for apply_memory in apply_memory_list: # 遍历每个申请的内存
flag = False # 标志位:是否成功分配
for i in range(len(memory_list)): # 遍历内存池
if memory_list[i] >= apply_memory: # 如果当前内存块满足申请
flag = True # 设置标志位为 True
memory_list.pop(i) # 从内存池中移除已分配的内存块
break # 跳出循环
result_list.append(flag) # 将分配结果添加到结果列表
# 输出结果
print(",".join(["true" if result else "false" for result in result_list])) # 转为小写输出结果
if __name__ == "__main__":
main()
JavaScript
// 导入模块
const readline = require("readline");
// 创建接口,用于读取用户输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
// 主函数
rl.on("line", (memoryInfo) => {
rl.on("line", (applyList) => {
// 内存信息
let memoryList = []; // 创建一个数组用于存储内存池
let memoryInfoList = memoryInfo.split(","); // 按逗号分割内存池信息
memoryInfoList.forEach((info) => {
let [size, count] = info.split(":").map(Number); // 提取内存块大小和数量
for (let i = 0; i < count; i++) {
memoryList.push(size); // 根据数量添加到内存池数组
}
});
// 排序内存池,优先从小到大分配更精准的内存
memoryList.sort((a, b) => a - b);
// 申请信息
let applyMemoryList = applyList.split(",").map(Number); // 将申请列表按逗号分割并转为数字数组
// 分配内存
let resultList = []; // 存储每次申请是否成功的结果
applyMemoryList.forEach((applyMemory) => {
let flag = false; // 标志位:是否成功分配
for (let i = 0; i < memoryList.length; i++) {
if (memoryList[i] >= applyMemory) {
flag = true; // 设置标志位为 True
memoryList.splice(i, 1); // 从内存池中移除已分配的内存块
break; // 跳出循环
}
}
resultList.push(flag); // 添加分配结果
});
// 输出结果
console.log(resultList.join(",")); // 输出结果,用逗号分隔
rl.close();
});
});
C++
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
int main() {
// 输入内存池资源和申请列表
string memoryInfo, applyList;
cin >> memoryInfo;
cin >> applyList;
// 内存信息
vector<int> memoryList;
stringstream memoryStream(memoryInfo);
string memoryBlock;
while (getline(memoryStream, memoryBlock, ',')) { // 按逗号分割内存信息
int colonIndex = memoryBlock.find(":");
int size = stoi(memoryBlock.substr(0, colonIndex)); // 提取内存块大小
int count = stoi(memoryBlock.substr(colonIndex + 1)); // 提取内存块数量
for (int i = 0; i < count; i++) {
memoryList.push_back(size); // 根据数量添加到内存池
}
}
// 排序内存池,优先从小到大分配更精准的内存
sort(memoryList.begin(), memoryList.end());
// 申请信息
vector<int> applyMemoryList;
stringstream applyStream(applyList);
string applyBlock;
while (getline(applyStream, applyBlock, ',')) { // 按逗号分割申请列表
applyMemoryList.push_back(stoi(applyBlock));
}
// 分配内存
vector<bool> resultList; // 存储每次申请是否成功的结果
for (int applyMemory : applyMemoryList) {
bool flag = false; // 标志位:是否成功分配
for (auto it = memoryList.begin(); it != memoryList.end(); ++it) {
if (*it >= applyMemory) {
flag = true; // 设置标志位为 True
memoryList.erase(it); // 移除已分配的内存块
break; // 跳出循环
}
}
resultList.push_back(flag); // 添加分配结果
}
// 输出结果
for (size_t i = 0; i < resultList.size(); i++) {
cout << (resultList[i] ? "true" : "false");
if (i != resultList.size() - 1) {
cout << ",";
}
}
return 0;
}
C语言
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_MEMORY_BLOCKS 1000
#define MAX_APPLY_REQUESTS 1000
int compare(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
int main() {
char memoryInfo[1024], applyList[1024];
int memoryList[MAX_MEMORY_BLOCKS]; // 存储内存块
int memoryCount = 0; // 内存块总数
int applyMemoryList[MAX_APPLY_REQUESTS]; // 申请内存大小列表
int applyCount = 0; // 申请总数
int resultList[MAX_APPLY_REQUESTS]; // 存储申请结果
// 输入内存池信息和申请列表
scanf("%s", memoryInfo);
scanf("%s", applyList);
// 处理内存池信息
char *memoryToken = strtok(memoryInfo, ",");
while (memoryToken != NULL) {
char *colon = strchr(memoryToken, ':');
if (colon == NULL) {
fprintf(stderr, "错误:内存池信息格式不正确。\n");
return 1;
}
*colon = '\0';
int size = atoi(memoryToken);
int count = atoi(colon + 1);
for (int i = 0; i < count; i++) {
memoryList[memoryCount++] = size;
}
memoryToken = strtok(NULL, ",");
}
// 对内存块排序(升序)
qsort(memoryList, memoryCount, sizeof(int), compare);
// 处理申请列表
char *applyToken = strtok(applyList, ",");
while (applyToken != NULL) {
int applySize = atoi(applyToken);
applyMemoryList[applyCount++] = applySize;
applyToken = strtok(NULL, ",");
}
// 分配内存
for (int i = 0; i < applyCount; i++) {
int applyMemory = applyMemoryList[i];
int allocated = 0; // 标志是否成功分配
for (int j = 0; j < memoryCount; j++) {
if (memoryList[j] >= applyMemory) {
allocated = 1; // 成功分配
// 移除已分配内存块,通过覆盖方式
for (int k = j; k < memoryCount - 1; k++) {
memoryList[k] = memoryList[k + 1];
}
memoryCount--; // 更新内存块总数
break;
}
}
resultList[i] = allocated; // 保存结果
}
// 输出分配结果
for (int i = 0; i < applyCount; i++) {
printf(resultList[i] ? "true" : "false");
if (i != applyCount - 1) {
printf(",");
}
}
printf("\n");
return 0;
}
完整用例
用例1
64:2,128:1,32:4,1:128
50,36,64,128,127
用例2
32:3,64:1,128:2,8:5
16,64,33,8,130
用例3
16:4,32:2,128:1,256:1
32,32,256,128,64
用例4
8:5,16:3,32:2,128:1
10,15,8,16,200
用例5
1:10,2:5,4:3,8:2
2,4,1,1,10
用例6
64:1,128:1,256:2
128,64,256,256,300
用例7
64:2,128:1,32:4,16:6
16,32,64,128,64,32
用例8
64:3,128:2,256:1
256,128,128,64,64,64
用例9
32:5,64:4,128:2,256:1
128,64,32,64,256,32,32
用例10
64:2,128:1,256:1
300,128,64,64,64