题解

题面描述

有一个总空间为 100 字节的堆,现要从中新申请一块内存,内存分配原则为:

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

思路

这道题的思路是首先对已分配的内存块进行合法性检查,确保所有内存块的起始地址和大小在堆的范围内且没有重叠。然后,将已分配的内存块按照起始地址排序,接着识别出所有空闲的内存区域。接下来,根据内存分配的优先原则,优先选择紧接着前一块已使用内存的空闲区,并在满足申请大小的空闲区中选择最接近申请大小的区域。最后,若找到合适的空闲区,则输出其起始地址,否则输出 -1 表示分配失败。通过这种方法,能够深入有效地管理和分配堆内存,确保分配的最优性和合理性。

  1. 输入合法性检查:

检查所有已分配内存块的起始地址和大小是否在 0 到 100 的范围内。
检查已分配内存块之间是否有重叠。

  1. 构建已分配内存块列表:

读取所有已分配的内存块,并按照起始地址排序。

  1. 找到所有空闲内存块:

遍历已分配内存块之间的空隙,记录所有空闲内存块的位置和大小。
考虑起始到第一个已分配块之前和最后一个已分配块到堆末尾的空闲空间。

  1. 按照分配原则选择合适的空闲内存块:

优先选择紧接着前一块已使用内存的空闲块。
在满足大小要求的空闲块中,选择最接近申请大小的块。

  1. 输出结果:

如果找到合适的空闲块,输出其起始地址。
否则,输出 −1。

python

import sys

# 定义内存块类
class MemoryBlock:
    def __init__(self, start, size):
        self.start = start
        self.size = size

def main():
    lines = sys.stdin.read().splitlines()
    if not lines:
        print(-1)
        return
    try:
        request_size = int(lines[0])
    except:
        print(-1)
        return

    allocated = []
    for line in lines[1:]:
        parts = line.strip().split()
        if len(parts) !=2:
            print(-1)
            return
        try:
            start, size = map(int, parts)
            allocated.append(MemoryBlock(start, size))
        except:
            print(-1)
            return

    # 合法性检查
    for block in allocated:
        if block.start <0 or block.size <=0 or block.start + block.size >100:
            print(-1)
            return

    # 按起始地址排序
    allocated.sort(key=lambda x: x.start)

    # 检查重叠
    for i in range(1, len(allocated)):
        prev = allocated[i-1]
        curr = allocated[i]
        if curr.start < prev.start + prev.size:
            print(-1)
            return

    # 找出空闲内存块
    free_blocks = []
    if not allocated:
        free_blocks.append(MemoryBlock(0, 100))
    else:
        if allocated[0].start >0:
            free_blocks.append(MemoryBlock(0, allocated[0].start))
        for i in range(1, len(allocated)):
            prev_end = allocated[i-1].start + allocated[i-1].size
            curr_start = allocated[i].start
            if curr_start > prev_end:
                free_blocks.append(MemoryBlock(prev_end, curr_start - prev_end))
        last_end = allocated[-1].start + allocated[-1].size
        if last_end <100:
            free_blocks.append(MemoryBlock(last_end, 100 - last_end))

    # 查找满足条件的空闲块
    candidates = [block for block in free_blocks if block.size >= request_size]
    if not candidates:
        print(-1)
        return

    # 选择最接近申请大小的块
    candidates.sort(key=lambda x: (x.size - request_size, x.start))
    best_start = candidates[0].start
    print(best_start)

if __name__ == "__main__":
    main()

java

import java.util.*;
import java.io.*;

class MemoryBlock implements Comparable<MemoryBlock>{
    int start;
    int size;

    MemoryBlock(int start, int size){
        this.start = start;
        this.size = size;
    }

    @Override
    public int compareTo(MemoryBlock other){
        return this.start - other.start;
    }
}

public class Main {
    public static void main(String[] args) throws IOException{
        Scanner sc = new Scanner(System.in);
        if(!sc.hasNextInt()){
            System.out.println("-1");
            return;
        }
        int request_size = sc.nextInt();
        List<MemoryBlock> allocated = new ArrayList<>();
        while(sc.hasNextInt()){
            int start = sc.nextInt();
            if(!sc.hasNextInt()){
                System.out.println("-1");
                return;
            }
            int size = sc.nextInt();
            allocated.add(new MemoryBlock(start, size));
        }

        // 合法性检查
        for(MemoryBlock block : allocated){
            if(block.start <0 || block.size <=0 || block.start + block.size >100){
                System.out.println("-1");
                return;
            }
        }

        // 按起始地址排序
        Collections.sort(allocated);

        // 检查重叠
        for(int i=1;i<allocated.size();i++){
            MemoryBlock prev = allocated.get(i-1);
            MemoryBlock curr = allocated.get(i);
            if(curr.start < prev.start + prev.size){
                System.out.println("-1");
                return;
            }
        }

        // 找出空闲内存块
        List<MemoryBlock> free_blocks = new ArrayList<>();
        if(allocated.isEmpty()){
            free_blocks.add(new MemoryBlock(0, 100));
        }
        else{
            if(allocated.get(0).start >0){
                free_blocks.add(new MemoryBlock(0, allocated.get(0).start));
            }
            for(int i=1;i<allocated.size();i++){
                int prev_end = allocated.get(i-1).start + allocated.get(i-1).size;
                int curr_start = allocated.get(i).start;
                if(curr_start > prev_end){
                    free_blocks.add(new MemoryBlock(prev_end, curr_start - prev_end));
                }
            }
            int last_end = allocated.get(allocated.size()-1).start + allocated.get(allocated.size()-1).size;
            if(last_end <100){
                free_blocks.add(new MemoryBlock(last_end, 100 - last_end));
            }
        }

        // 查找满足条件的空闲块
        List<MemoryBlock> candidates = new ArrayList<>();
        for(MemoryBlock block : free_blocks){
            if(block.size >= request_size){
                candidates.add(block);
            }
        }

        if(candidates.isEmpty()){
            System.out.println("-1");
            return;
        }

        // 选择最接近申请大小的块
        Collections.sort(candidates, new Comparator<MemoryBlock>(){
            public int compare(MemoryBlock a, MemoryBlock b){
                if((a.size - request_size) != (b.size - request_size)){
                    return (a.size - request_size) - (b.size - request_size);
                }
                return a.start - b.start;
            }
        });

        int best_start = candidates.get(0).start;
        System.out.println(best_start);
    }
}

cpp

#include <bits/stdc++.h>
using namespace std;

// 定义内存块结构体
struct MemoryBlock {
    int start; // 起始地址
    int size;  // 大小

    bool operator<(const MemoryBlock& other) const {
        return start < other.start;
    }
};

int main(){
    int request_size;
    // 读取申请的内存大小
    if(!(cin >> request_size)){
        cout << "-1";
        return 0;
    }

    vector<MemoryBlock> allocated;
    int start, size;
    // 读取已分配的内存块
    while(cin >> start >> size){
        allocated.push_back({start, size});
    }

    // 合法性检查
    // 检查每个内存块是否在范围内
    for(auto &block : allocated){
        if(block.start < 0 || block.size <=0 || block.start + block.size > 100){
            cout << "-1";
            return 0;
        }
    }

    // 按起始地址排序
    sort(allocated.begin(), allocated.end());

    // 检查是否有重叠
    for(int i=1;i<allocated.size();i++){
        if(allocated[i].start < allocated[i-1].start + allocated[i-1].size){
            cout << "-1";
            return 0;
        }
    }

    // 找出所有空闲内存块
    vector<MemoryBlock> free_blocks;
    // 如果第一个已分配块不是从0开始
    if(allocated.empty()){
        free_blocks.push_back({0, 100});
    }
    else{
        if(allocated[0].start > 0){
            free_blocks.push_back({0, allocated[0].start});
        }
        for(int i=1;i<allocated.size();i++){
            int prev_end = allocated[i-1].start + allocated[i-1].size;
            int curr_start = allocated[i].start;
            if(curr_start > prev_end){
                free_blocks.push_back({prev_end, curr_start - prev_end});
            }
        }
        // 检查最后一个块到堆末尾的空闲空间
        int last_end = allocated.back().start + allocated.back().size;
        if(last_end < 100){
            free_blocks.push_back({last_end, 100 - last_end});
        }
    }

    // 按分配原则查找合适的空闲块
    // 优先紧接着前一块已使用内存
    // 然后选择最接近申请大小的块
    // 首先查找所有满足大小的块
    vector<MemoryBlock> candidates;
    for(auto &block : free_blocks){
        if(block.size >= request_size){
            candidates.push_back(block);
        }
    }

    if(candidates.empty()){
        cout << "-1";
        return 0;
    }

    // 找到最接近申请大小的块
    // 如果有多个,选择起始地址最小的
    int best_start = -1;
    int min_diff = INT32_MAX;
    for(auto &block : candidates){
        int diff = block.size - request_size;
        if(diff < min_diff || (diff == min_diff && block.start < best_start)){
            min_diff = diff;
            best_start = block.start;
        }
    }

    cout << best_start;
    return 0;
}


灵芸小骏
9k 声望846 粉丝

移动开发者。