内存资源分配_200分_A/B卷复用_逻辑分析模拟/二分查找/数据结构

内存资源分配

题目描述:

有一个简易内存池,内存按照大小粒度分类,每个粒度有若干个可用内存资源,
用户会进行一系列内存申请,需要按需分配内存池中的资源 返回申请结果成功失败列表。
分配规则如下:
  分配的内存要大于等于内存的申请量,存在满足需求的内存就必须分配,优先分配粒度小的,但内存不能拆分使用;
  需要按申请顺序分配,先申请的先分配,
  有可用内存分配则申请结果为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

解题思路:

1、先统计出所有不同粒度的内存及其数量,此处使用Map来统计,key为粒度大小,value为数量。同时记录下所有粒度。
2、对所有粒度进行排序,这样可以在请求分配内存的时候使用二分查找加快查找速度
3、模拟内存分配:
  ①从还可以选择的内存粒度中选择一个大于等于申请内存的粒度,如果该内存太大,没有内存可用,则为false
  ②从map中挑选出对应粒度的硬盘,同时当前粒度数量减1,并判断是否用完,用完的话需要将粒度删除掉。

代码:

public static void main(String[] args) {
	Scanner scanner = new Scanner(System.in);
	String[] split = scanner.nextLine().split(",");
	String[] requests = scanner.nextLine().split(",");

	Map<Integer, Integer> map = new HashMap<>();
	List<Integer> types = new ArrayList<>();
	// 统计不同大小的内存及其数量
	for (String s : split) {
		String[] item = s.split(":");
		int key = Integer.parseInt(item[0]);
		int count = Integer.parseInt(item[1]);
		if (map.containsKey(key)) {
			map.put(key, map.get(key) + count);
		} else {
			map.put(key, count);
			types.add(key);
		}
	}
	// 排序
	Collections.sort(types);

	StringBuilder sb = new StringBuilder();
	int index = 0;
	for (String item : requests) {
		int target = Integer.parseInt(item);
		if (map.isEmpty()) {
			if (index++ > 0) {
				sb.append(",false");
			} else {
				sb.append("false");
			}
		}

		// 二分查找:找出一个最小的 且大于 target 的内存
		int left = 0;
		int right = types.size() - 1;
		while (left < right) {
			int mid = (right - left) / 2 + left;
			if (types.get(mid) < target) {
				// 缩小范围 [mid + 1,right]
				left = mid + 1;
			} else {
				// 缩小范围 [left, mid]
				right = mid;
			}
		}

		// 剩余的内存都很小,不够分配
		if (types.get(left) < target) {
			if (index++ > 0) {
				sb.append(",false");
			} else {
				sb.append("false");
			}
			continue;
		}

		// 还能分配
		Integer count = map.get(types.get(left));
		if (index++ > 0) {
			sb.append(",true");
		} else {
			sb.append("true");
		}

		if (count == 1) {
			// 最后一块,删除
			map.remove(types.get(left));
			types.remove(left);
		} else {
			map.put(types.get(left), count - 1);
		}
	}

	System.out.println(sb.toString());
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值