2025B-堆内存申请-100分

刷题笔记合集🔗

问题描述

小基负责管理一个总空间为 字节的堆内存。现在,他需要从中新申请一块内存。内存分配原则为:优先紧接着前一块已使用内存,分配空间足够且最接近申请大小的空闲内存。

输入格式

行是 个整数,表示期望申请的内存字节数。

到第 行是用空格分割的两个整数,表示当前已分配的内存的情况,每一行表示一块已分配的连续内存空间,每行的第 和第 个整数分别表示偏移地址和内存块大小。

输出格式

若申请成功,输出申请到内存的偏移;若申请失败,输出

样例输入1

1
0 1
3 2

样例输出1

1

样例输入2

10
0 20
30 10
50 10
70 10
90 10

样例输出2

20

样例输入3

30
0 20
30 10
50 10
70 10
90 10

样例输出3

-1

样例解释

样例 解释说明
样例1 堆中已使用的两块内存是偏移从0开始的1字节和偏移从3开始的2字节,空闲的两块内存是偏移从1开始2个字节和偏移从5开始95字节,根据分配原则,新申请的内存应从1开始分配1个字节,所以输出偏移为1。
样例2 堆中已使用的内存块分别是:0-19、30-39、50-59、70-79、90-99,空闲的内存块分别是:20-29、40-49、60-69、80-89。根据分配原则,新申请10字节的内存应从20开始分配,所以输出偏移为20。
样例3 堆中最大的空闲内存块只有10字节,无法满足申请30字节的需求,所以输出-1。

数据范围

  • 申请的内存大小
  • 偏移地址
  • 内存块大小
  • 已分配内存块数量不超过

题解

这道题目要求我们在一个总大小为100字节的堆内存中,按照特定规则申请一块新的内存。

首先,我们需要理解内存分配的原则:

  1. 优先紧接着前一块已使用内存
  2. 分配空间足够且最接近申请大小的空闲内存

解题思路如下:

  1. 首先检查申请的内存大小是否合法(大于0且不超过100)
  2. 将已分配的内存块按照起始位置(偏移地址)排序
  3. 遍历排序后的内存块,检查每个内存块的合法性:
    • 内存块的起始位置不应小于前一个内存块的结束位置(否则会有重叠)
    • 内存块的起始位置不应大于99
    • 内存块的大小应大于0且不超过从该位置到堆末尾的剩余空间
  4. 在遍历过程中,计算每两个相邻内存块之间的空闲空间大小
  5. 如果空闲空间足够大(大于等于申请的内存大小),且比之前找到的最佳空闲空间更接近申请大小,则更新最佳申请位置
  6. 最后,还需要检查最后一个已分配内存块之后到堆末尾的空闲空间

时间复杂度分析:

  • 对内存块排序需要 的时间
  • 遍历内存块需要 的时间
  • 因此,总时间复杂度为

对于给定的数据范围(内存块数量不超过100),这个复杂度是可以接受的。

参考代码

class Mem:
    def __init__(self, pos, len_val):
        """
        初始化内存块
        
        参数:
            pos: 内存块起始位置
            len_val: 内存块大小
        """
        self.pos = pos  # 内存块起始位置
        self.len = len_val  # 内存块大小


# 算法入口
def find_mem():
    """
    寻找合适的内存块
    
    返回:
        申请到的内存偏移,如果申请失败则返回-1
    """
    # 读取申请的内存大小
    req_size = int(input())
    
    # 读取已占用的内存
    used = []
    while True:
        try:
            p, s = map(int, input().split())
            used.append(Mem(p, s))
        except:
            break
    
    # 申请的内存大小非法,则返回-1
    if req_size <= 0 or req_size > 100:
        return -1
    
    # 记录最优的申请内存起始位置
    best_pos = -1
    # 记录最接近申请内存的空闲内存块大小
    min_size = 101
    
    # 对占用的内存按照起始位置升序
    used.sort(key=lambda x: x.pos)
    
    # 记录空闲内存块的起始位置
    free_pos = 0
    
    for blk in used:
        # 检查内存块是否合法
        if blk.pos < free_pos or blk.pos > 99:
            return -1
        
        if blk.len <= 0 or blk.len > 100 - blk.pos:
            return -1
        
        # 计算空闲内存块
        if blk.pos > free_pos:
            # 空闲内存块大小
            free_size = blk.pos - free_pos
            
            # 如果该空闲内存块大小足够,且最接近申请的内存大小
            if req_size <= free_size < min_size:
                best_pos = free_pos
                min_size = free_size
        
        # 更新空闲内存的起始位置
        free_pos = blk.pos + blk.len
    
    # 检查最后一个空闲内存块
    last_free = 100 - free_pos
    if req_size <= last_free < min_size:
        best_pos = free_pos
    
    return best_pos


# 主函数
if __name__ == "__main__":
    print(find_mem())
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

/**
 * 内存块结构体
 */
struct Blk {
    int pos;  // 内存块起始位

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

算法刷题笔记 文章被收录于专栏

本专栏收集并整理了一些刷题笔记

全部评论

相关推荐

那一天的Java_J...:他本来公司就是做这个的,不就是正常的游戏客户端和服务器开发,软硬件联动,有啥恶心不恶心的,提前告诉你就是怕你接受不了,接受不了就没必要再往后走流程浪费时间,虽然这公司是一坨。
点赞 评论 收藏
分享
06-27 12:54
已编辑
门头沟学院 Java
累了,讲讲我的大学经历吧,目前在家待业。我是一个二本院校软件工程专业。最开始选专业是觉得计算机感兴趣,所以选择了他。本人学习计算机是从大二暑假结束开始的,也就是大三开始。当时每天学习,我个人认为Java以及是我生活的一部分了,就这样持续学习了一年半,来到了大四上学期末,大概是在12月中旬,我终于找的到了一家上海中厂的实习,但我发现实习生的工作很枯燥,公司分配的活也不多,大多时间也是自己在自学。就这样我秋招末才找到实习。时间来到了3月中旬,公司说我可以转正,但是转正工资只有7000,不过很稳定,不加班,双休,因为要回学校参加答辩了,同时当时也是心高气傲,认为可以找到更好的,所以放弃了转正机会,回学校准备论文。准备论文期间就也没有投递简历。然后时间来到了5月中旬,这时春招基本也结束了,然后我开始投递简历,期间只是约到了几家下场面试。工资也只有6-7k,到现在我不知道该怎么办了。已经没有当初学习的心劲了,好累呀,但是又不知道该干什么去。在家就是打游戏,boss简历投一投。每天日重一次。26秋招都说是针对26届的人,25怎么办。我好绝望。要不要参加考公、考研、央国企这些的。有没有大佬可以帮帮我。为什么感觉别人找工作都是顺其自然的事情,我感觉自己每一步都在艰难追赶。八股文背了又忘背了又忘,我每次都花很长时间去理解他,可是现在感觉八股、项目都忘完了。真的已经没有力气再去学习了。图片是我的简历,有没有大哥可以指正一下,或者说我应该走哪条路,有点不想在找工作了。
码客明:太累了就休息一下兄弟,人生不会完蛋的
如果实习可以转正,你会不...
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务