机试题——分配资源 ID

题目描述

给定一个管理 ID 的资源池,可以从资源池中分配资源 ID 和释放资源 ID,分配方式有动会正态分配和指定分配,动态分配是从资源池的开始分配一个资源 ID,指定分配是指定个资源 ID 进行分配,无论哪种分配方式释放资源 ID 时都需要放到资源池的尾部。执行系列操作后,请问资源池的第一个空闲资源 ID 应该是多少?

注意: 资原池的初始顺序是从小到大。 资源池中空闲资源 ID 不足时,动态分配失败,对资源池不进行任何操作。 指定分配资源 ID 已经被占用或者不在资源池范围内时,对资源池不进行任何操作。 释放资源 ID 不在资源池范围内时或者已经是空闲资源 ID 时,对资源池不进行任何操作。 保证每个用例最后都有空闲资源 ID。

输入描述

第一行是资源池的范国; 第二行是操作个数。 第三行开始,第一个数字代表操作类型,1 表示动态分配,2 表示指定分配,3 表示释放; 如果第一个数字是 1,第一个表示分配的个数; 如果第一个数字是 2,第二个表示分配的资源 ID; 如果第一个数字是 3,第二个表示释放的资源 ID,

输出描述

资源池的第一个空闲资源 ID。

用例输入

输入:

bash 复制代码
1 3
2
1 1
3 1

输出:

bash 复制代码
2

解释:

第一行资源池范围是1,3,资源池的初始顺序是1->2->3。

第二行操作个数有2个。

第三行动态分配1个资源ID,资源池中剩余的资源ID顺序是2->3。

有四行释放1个资源ID,资源ID是1,资源池中剩余的资源ID顺序是2->3->1。

执行以上操作后,资源池的第一个空闲资源ID是2。

输入:

bash 复制代码
1 3
3
2 2
3 2
1 1

输出:

bash 复制代码
3

解释:

第一行行资源池范围是1,3,资源池的初始顺序是1->2->3。

第二行操作个数有3个。

第三行指定分配1个资源ID,资源ID是2,资源池中剩余的资源ID顺序是1->3。

第四行释放1个资源ID,资源ID是2,资源池中剩余的资源ID顺序是1->3->2。

第五行动态分配1个资源ID,分配的资源D是1,资源池中剩余的资源ID顺序是3->2。

执行以上操作后,资源池的第一个空闲资源ID是3。

保证输入的操作都是合法的。 操作类型范围是 1,3。 分配次数范围是 1,100000

解题思路

首先看分配的情况:

动态分配是从资源池的开始分配一个资源 ID,指定分配是指定个资源 ID 进行分配 。 也就是是需要一种数据结构,可以获取其头部元素和其中指定的ID元素。

无论哪种分配方式释放资源 ID 时都需要放到资源池的尾部。 这个数据结构还需要支持尾部插入。

资源池中空闲资源 ID 不足时,动态分配失败,对资源池不进行任何操作。 指定分配资源 ID 已经被占用或者不在资源池范围内时,对资源池不进行任何操作。 释放资源 ID 不在资源池范围内时或者已经是空闲资源 ID 时,对资源池不进行任何操作。

还需要查询是否有空闲资源,被分配出去的ID还需要记录。

使用双向list和map,双向list维护可用的id列表,map记录每一个id对应的链表节点,可以做到插入删除为O(n),查询一个id对应的节点为O(logn)。

再使用一个bool数组,维护已经被使用的id,如果被使用则为1,没有被使用则为0。

代码

cpp 复制代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>
#include<string>
#include<vector>
#include<unordered_map>
#include<unordered_set>
#include<queue>
#include<set>
#include<list>
using namespace std;
const int maxn = 100004;

vector<int> flag(maxn, 0);//标记数组
list<int> pool;//资源池
map<int, list<int>::iterator> mp;// id对应的list节点迭代器
int main()
{
    ios::sync_with_stdio(false); 
    cin.tie(nullptr);  
    int l, r;// 资源池范围
    cin >> l >> r;
    for (int i = l; i <= r; i++) {
        pool.push_back(i);
        auto it = pool.end();
        it--;
        mp[i] = it;
    }
    int n,type;
    cin >> n;
    while (n--) {
        cin >> type;
        if (type == 1) { //动态分配
            int k;// 分配个数
            cin >> k;
            if (k > pool.size()) continue; //分配失败
            for (int i = 0; i < k; i++) {
                int id = pool.front();
                pool.pop_front();
                mp.erase(id);
                flag[id] = 1;// 已分配
            }
        }
        else if (type == 2) { //指定分配
            int id;
            cin >> id;
            if (flag[id] == 1) continue;// 已经分配了
            //没分配就删除映射
            pool.erase(mp[id]);
            mp.erase(id);
            flag[id] = 1;
        }
        else if (type == 3) { //释放资源
            int id;
            cin >> id;
            if (flag[id] == 0) continue;//压根没用资源不用释放
            pool.push_back(id); //增加资源和映射关系
            auto it = pool.end();
            it--;
            mp[id] = it;
            flag[id] = 0;//更新标记
        }
    }
    if (pool.empty()) {
        cout << "-1\n";
    }
    else {
        cout << pool.front()<<"\n";
    }
}

自测用例

混合动态分配、指定分配和释放

bash 复制代码
1 5
7
1 2
2 4
1 1
3 2
2 5
3 1
1 2

初始资源池:1, 2, 3, 4, 5

操作1:动态分配 2 个资源。

分配 1 和 2。

剩余资源池:3, 4, 5

操作2:指定分配资源 ID 4。

分配 4。

剩余资源池:3, 5

操作3:动态分配 1 个资源。

分配 3.

剩余资源池:5

操作4:释放资源 ID 2。

将 2 放到尾部。

资源池:5, 2

操作5:指定分配资源 ID 5。

分配 5.

剩余资源池:2

操作6:释放资源 ID 1.

将 1 放到尾部。

资源池:2, 1

操作7:动态分配 2 个资源。

分配 2 和 1.

资源池为空。

bash 复制代码
-1

释放未分配或无效资源 ID

bash 复制代码
1 4
6
3 2
1 1
3 2
2 3
3 4
1 2
bash 复制代码
-1

大量操作与边界条件

bash 复制代码
10 20
10
1 5
2 15
1 3
3 10
2 12
1 4
3 15
2 20
1 2
3 12
bash 复制代码
15
相关推荐
湖南天硕国产SSD6 分钟前
工业存储可靠性进阶:天硕工业固态硬盘动态温控与寿命优化技术实践
网络·数据库·算法·工业存储·天硕存储·工业固态硬盘
legend050709ComeON7 分钟前
常见面试题-leetcode
数据结构·算法·leetcode
Smilecoc16 分钟前
决策树(一):决策树基本原理
算法·决策树·机器学习
weixin_3077791319 分钟前
从工具到协作者:AI在后端研发中的流程重构与组织赋能
人工智能·后端·python·算法·自动化
沉下去,苦磨练!28 分钟前
深度学习神经网络的搭建
人工智能·算法
Lsk_Smion34 分钟前
力扣实训 _ [207].课程表/图论
数据结构·leetcode·图论
孬甭_42 分钟前
深入剖析快速排序:原理、实现与性能优化
数据结构·算法·排序算法
San813_LDD43 分钟前
[数据结构]共享栈与双端队列:算法思想分析及C语言实现
java·开发语言·数据结构
阿正的梦工坊1 小时前
【Rust】06-函数、控制流与模块组织
开发语言·算法·rust
阿正的梦工坊1 小时前
【Rust】16-async/await、Future 与执行器模型
网络·算法·rust