池化资源共享 - 华为OD机试真题(C++题解)

华为OD机试题库《C++》限时优惠 9.9

华为OD机试题库《Python》限时优惠 9.9

华为OD机试题库《JavaScript》限时优惠 9.9

针对刷题难,效率慢,我们提供一对一算法辅导, 针对个人情况定制化的提高计划(全称1V1效率更高)。

看不懂有疑问需要答疑辅导欢迎私VX: code5bug

华为OD机试真题

题目描述

有一个局部互联区域内的 n 台设备,每台设备都有一定数量的空闲资源,这些资源可以池化共享。用户会发起两种操作:

  1. 申请资源:输入 1 x,表示本次申请需要 x 个资源。系统要返回当前资源池中能满足此申请且剩余资源最少的设备 ID;如果有多台设备满足条件,返回设备 ID 最小的;如果没有任何设备能满足,返回 0 并不做任何分配。
  2. 释放资源:输入 2 y,表示将第 y 次申请(不一定是成功分配的那一次)释放回原设备。释放时,资源立即归还,且空闲资源自动连续,无需考虑空洞。

给定 n(1 ≤ n ≤ 1000)、操作次数 m(1 ≤ m ≤ 105),以及初始时每台设备的空闲资源数 d₁…dₙ(1 ≤ dᵢ ≤ 1000),以及接下来 m 行操作,输出每次 “申请” 操作的返回值。

输入描述

第一行,输入n和 m

第二行输入n台设备的初始空闲资源数

接下来m行,输出要执行的操作

输出描述

输出每次“申请”操作的返回值。

示例1

输入:

2 2
100 500
1 40
1 450

输出:

1 2

题解

这道题目属于 模拟题,主要考察对操作流程的模拟和数据结构的选择。需要处理两种操作:申请资源和释放资源,并根据特定规则返回结果。

解题思路

  1. 申请资源操作1 x):
    • 遍历所有设备,筛选出当前空闲资源大于 x 的设备。
    • 对这些设备按照剩余资源升序排序,如果剩余资源相同,则按照设备 ID 升序排序。
    • 如果找到满足条件的设备,选择剩余资源最少且 ID 最小的设备,分配资源,并记录分配历史。
    • 如果没有满足条件的设备,返回 0
  2. 释放资源操作2 y):
    • 根据历史记录找到第 y 次申请对应的设备和分配的资源量。
    • 将资源归还给原设备。

代码描述

  • 输入处理:读取设备数量 n 和操作次数 m,以及每台设备的初始空闲资源。
  • 操作处理
    • 对于申请操作,筛选并排序可用设备,分配资源并记录历史。
    • 对于释放操作,根据历史记录归还资源。
  • 输出结果:每次申请操作的返回值。

时间复杂度

  • 申请操作:每次申请需要遍历所有设备(O(n)),然后排序(O(n log n)),因此最坏情况下为 O(n log n)。
  • 释放操作:直接根据历史记录归还资源,O(1)。
  • 总时间复杂度:O(m * n log n),其中 m 是操作次数,n 是设备数量。

空间复杂度

  • 需要存储设备空闲资源数组(O(n))和历史记录(O(m))。
  • 总空间复杂度:O(n + m)。

C++

// Author: code5bug
#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, m;
    cin >> n >> m;  // 设备数量,操作次数
    vector<int> free(n);  // 每台设备的空闲资源数
    for (int i = 0; i < n; i++) {
        cin >> free[i];
    }

    // 历史记录:保存每次申请的设备索引和分配的资源量
    vector<pair<int, int>> history;
    // 保存每次申请操作的返回值
    vector<int> result;

    for (int i = 0; i < m; i++) {
        int type, v;
        cin >> type >> v;  // 操作类型和参数
        // 申请资源操作
        if (type == 1) {
            // 筛选出空闲资源足够的设备
            vector<pair<int, int>> tmp;
            for (int j = 0; j < n; j++) {
                if (free[j] >= v) {
                    tmp.emplace_back(free[j], j);
                }
            }
            // 按剩余资源升序排序,若相同则按设备ID升序排序
            sort(tmp.begin(), tmp.end(), [](const pair<int, int>& a, const pair<int, int>& b) {
                return a.first != b.first ? a.first < b.first : a.second < b.second;
            });
            if (!tmp.empty()) {
                int idx = tmp[0].second;  // 选择剩余资源最少且ID最小的设备
                free[idx] -= v;           // 分配资源
                history.emplace_back(idx, v);
                result.push_back(idx + 1);  // 设备ID从1开始
            } else {
                // 没有设备满足条件
                history.emplace_back(-1, 0);
                result.push_back(0);
            }
        }
        // 释放资源操作
        else if (type == 2) {
            auto [idx, size] = history[v - 1];  // 获取第v次申请的历史记录
            if (idx != -1) {
                free[idx] += size;  // 归还资源
            }
        }
    }

    // 输出结果
    for (int res : result) {
        cout << res << " ";
    }
    return 0;
}

希望这个专栏能让您熟练掌握算法, 🎁🎁🎁。

整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

什码情况

你的鼓励就是我最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值