给你一个二维数组 tasks ,用于表示 n 项从 0 到 n - 1 编号的任务。其中 tasks[i] = [enqueueTimei, processingTimei] 意味着第 i 项任务将会于 enqueueTimei 时进入任务队列,需要 processingTimei 的时长完成执行。
现有一个单线程 CPU ,同一时间只能执行 最多一项 任务,该 CPU 将会按照下述方式运行:
如果 CPU 空闲,且任务队列中没有需要执行的任务,则 CPU 保持空闲状态。
如果 CPU 空闲,但任务队列中有需要执行的任务,则 CPU 将会选择 执行时间最短 的任务开始执行。如果多个任务具有同样的最短执行时间,则选择下标最小的任务开始执行。
一旦某项任务开始执行,CPU 在 执行完整个任务 前都不会停止。
CPU 可以在完成一项任务后,立即开始执行一项新任务。
返回 CPU 处理任务的顺序。
You are given n tasks labeled from 0 to n - 1 represented by a 2D integer array tasks, where tasks[i] = [enqueueTimei, processingTimei] means that the ith task will be available to process at enqueueTimei and will take processingTimei to finish processing.
You have a single-threaded CPU that can process at most one task at a time and will act in the following way:
If the CPU is idle and there are no available tasks to process, the CPU remains idle.
If the CPU is idle and there are available tasks, the CPU will choose the one with the shortest processing time. If multiple tasks have the same shortest processing time, it will choose the task with the smallest index.
Once a task is started, the CPU will process the entire task without stopping.
The CPU can finish a task then start a new one instantly.
Return the order in which the CPU will process the tasks.
示例 1:
输入:tasks = [[1,2],[2,4],[3,2],[4,1]]
输出:[0,2,3,1]
解释:事件按下述流程运行:
- time = 1 ,任务 0 进入任务队列,可执行任务项 = {0}
- 同样在 time = 1 ,空闲状态的 CPU 开始执行任务 0 ,可执行任务项 = {}
- time = 2 ,任务 1 进入任务队列,可执行任务项 = {1}
- time = 3 ,任务 2 进入任务队列,可执行任务项 = {1, 2}
- 同样在 time = 3 ,CPU 完成任务 0 并开始执行队列中用时最短的任务 2 ,可执行任务项 = {1}
- time = 4 ,任务 3 进入任务队列,可执行任务项 = {1, 3}
- time = 5 ,CPU 完成任务 2 并开始执行队列中用时最短的任务 3 ,可执行任务项 = {1}
- time = 6 ,CPU 完成任务 3 并开始执行任务 1 ,可执行任务项 = {}
- time = 10 ,CPU 完成任务 1 并进入空闲状态
示例 2:
输入:tasks = [[7,10],[7,12],[7,5],[7,4],[7,2]]
输出:[4,3,2,0,1]
解释:事件按下述流程运行:
- time = 7 ,所有任务同时进入任务队列,可执行任务项 = {0,1,2,3,4}
- 同样在 time = 7 ,空闲状态的 CPU 开始执行任务 4 ,可执行任务项 = {0,1,2,3}
- time = 9 ,CPU 完成任务 4 并开始执行任务 3 ,可执行任务项 = {0,1,2}
- time = 13 ,CPU 完成任务 3 并开始执行任务 2 ,可执行任务项 = {0,1}
- time = 18 ,CPU 完成任务 2 并开始执行任务 0 ,可执行任务项 = {1}
- time = 28 ,CPU 完成任务 0 并开始执行任务 1 ,可执行任务项 = {}
- time = 40 ,CPU 完成任务 1 并进入空闲状态
提示:
tasks.length == n
1 <= n <= 105
1 <= enqueueTimei, processingTimei <= 109
class Solution {
public class Task{
public int i;
public int intime;
public int processTime;
public Task(int i,int intime,int processTime){
this.i=i;
this.intime=intime;
this.processTime=processTime;
}
}
public int[] getOrder(int[][] tasks) {
//入口
List<Task> taskList=new ArrayList();
for(int i=0;i<tasks.length;i++){
taskList.add(new Task(i,tasks[i][0],tasks[i][1]));
}
Collections.sort(taskList,(a,b)->a.intime-b.intime);
PriorityQueue<Task> queue=new PriorityQueue(new PriorityQueue<Task>((t1,t2) -> {
if(t1.processTime == t2.processTime){
//当执行时间相同时,根据id升序
return t1.i - t2.i;
}else{
//当执行时间不同时,根据执行时间升序
return t1.processTime - t2.processTime;
}
}));
int now=0;
int i=0;
int length=tasks.length;
int[] res=new int[length];
int p=0;
while (i<length){
while(i<length && taskList.get(i).intime<=now){
queue.offer(taskList.get(i));
i++;
}
if(queue.isEmpty()){
now=taskList.get(i).intime;
while(i<length && taskList.get(i).intime==now){
queue.offer(taskList.get(i));
i++;
}
}
Task task=queue.poll();
res[p++]=task.i;
now+=task.processTime;
}
while(!queue.isEmpty()){
res[p++]=queue.poll().i;
}
return res;
}
}
这道题目主要就是优先队列的使用,学会优先队列的用法该题目解析起来就很简单了
还有定义一个合理的数据结构来保存数据对于代码编写是很有帮助的。
难点在于想通每个时间段会发生的时间,以时间为序,来思考逻辑。
以一个一个时间片段为单位
每次增加时间片段的时候,cpu先是要看看有没有正在执行的任务,
有正在执行的任务是不能中止的,所以当启动一个任务的时候,就可以直接跳转到任务执行完成的时间。
当cpu没有需要执行的任务的时候,就要判断哪些任务是当前时间点需要执行的任务,即在当前时间点之前的全部没有完成的任务,所以这里用到了队列来保存需要执行的任务
得到需要执行的任务了,那么哪个任务的优先级最高呢,所以这里用到了优先队列,因为不是时间越早就优先级越高
以上,个人理解,欢迎指导