批量处理任务_100分_A/B卷复用_贪心策略

批量处理任务

题目描述:

某实验室计算机待处理任务以 [start,end,period] 格式记于二维数组 tasks,
表示完成该任务的时间范围:为起始时间 start 至结束时间 end 之间,需要计算机投入 period 的时长,
注意:
  period 可为不连续时间
  首尾时间均包含在内
处于开机状态的计算机可同时处理任意多个任务,请返回电脑最少开机多久,可处理完所有任务。
提示:
  2 <= tasks.length <= 10^5
  tasks[i].length == 3
  0 <= tasks[i][0] <= tasks[i][1] <= 10^9
  1 <= tasks[i][2] <= tasks[i][1]-tasks[i][0] + 1

输入输出描述:

输入描述:

  一个二维数组

输出描述:

  电脑最少开机多久

示例1:

输入:
	tasks = [[1,3,2],[2,5,3],[5,6,2]]
输出:
	4
解释:
	tasks[0] 选择时间点 2、3;
	tasks[1] 选择时间点 2、3、5;
	tasks[2] 选择时间点 5、6;
	因此计算机仅需在时间点 2、3、5、6 四个时刻保持开机即可完成任务。

示例2:
输入:
tasks = [[2,3,1],[5,5,1],[5,6,2]]
输出:
3
解释:
tasks[0] 选择时间点 2 或 3;
tasks[1] 选择时间点 5;
tasks[2] 选择时间点 5、6;
因此计算机仅需在时间点 2、5、6 或 3、5、6 三个时刻保持开机即可完成任务。

解题思路:

本题同LeetCode上的原题LCP 32. 批量处理任务;较优的解题思路在题解里面可以查看,本题的代码也是来自己LeetCode灵神的题解。

采用贪心策略:尽可能的让两个任务之间的运行时间重叠。
1、先对任务按照结束时间进行排序
2、开辟一个长度为最大的结束时间的数组run,为了标记在那些时刻在运行中
3、从排序后的任务列表开始遍历:
  对于当前任务,从结束时间开始可查看那些时间已经在run数组中(即在这写时间点的时间可算作该任务的运行时间)。
  若任务的所有运行时间都能够从run中减掉,则说明当前任务可与之前的那些任务进行并行运行,不需额外的时间。
  若任务还需要额外的时间进行才能运行结束。开启额外的时间时,优先开启靠近结束时间、且未在run中的时间点,这样可以尽可能的与后面的任务时间重叠,减少总的运行时间。

代码:

public static void main(String[] args) {
	Scanner scanner = new Scanner(System.in);
	String line = scanner.nextLine();
	int index = line.indexOf("[");
	String[] split = line.substring(index + 2, line.length() - 2).replace("],[", "#").split("#");
	int n = split.length;
	int[][] tasks = new int[n][3];

	// 输入处理
	for (int i = 0; i < n; i++) {
		String[] tmp = split[i].split(",");
		tasks[i][0] = Integer.parseInt(tmp[0]);
		tasks[i][1] = Integer.parseInt(tmp[1]);
		tasks[i][2] = Integer.parseInt(tmp[2]);
	}

	// 按照每个任务的 end 时间点进行排序
	Arrays.sort(tasks, (a, b)->a[1] - b[1]);
	// 以最后一个任务的结束时间为长度,创建一个:标记计算机在某时间点是否在运行
	boolean[] run = new boolean[tasks[n - 1][1] + 1];
	int res = 0;

	for (int[] item : tasks) {
		// 任务的起始时间、结束时间、运行时间
		int start = item[0];
		int end = item[1];
		int period = item[2];

		// 从任务的的结束时间开始遍历,减去已经运行掉的时间
		for (int i = end; i >= start && period > 0; i--) {
			if (run[i]) {
				period--;
			}
		}

		// 如果该任务还需要额外的时间才能运行结束,优先开启靠结束时间近的时间点
		for (int i = end; i >= start && period > 0; i--) {
			if (!run[i]) {
				run[i] = true;
				period--;
				res++;
			}
		}
	}

	// 统计运行的时间
	System.out.println(res);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值