1834. 单线程 CPU

74 阅读2分钟

题目:
给你一个二维数组 tasks ,用于表示 n​​​​​​ 项从 0n - 1 编号的任务。其中 tasks[i] = [enqueueTimei, processingTimei] 意味着第 i​​​​​​​​​​ 项任务将会于 enqueueTimei 时进入任务队列,需要 processingTimei 的时长完成执行。

现有一个单线程 CPU ,同一时间只能执行 最多一项 任务,该 CPU 将会按照下述方式运行:

  • 如果 CPU 空闲,且任务队列中没有需要执行的任务,则 CPU 保持空闲状态。
  • 如果 CPU 空闲,但任务队列中有需要执行的任务,则 CPU 将会选择 执行时间最短 的任务开始执行。如果多个任务具有同样的最短执行时间,则选择下标最小的任务开始执行。
  • 一旦某项任务开始执行,CPU 在 执行完整个任务 前都不会停止。
  • CPU 可以在完成一项任务后,立即开始执行一项新任务。

返回 **CPU **处理任务的顺序。

算法:
方法一:模拟

func getOrder(tasks [][]int) []int {
    // 队列需要新增,删除,取processingTimes最短的任务,用堆
    // 任务按进入调度队列时间排序
    for i := range tasks {
        tasks[i] = append(tasks[i], i)
    }
    sort.Slice(tasks, func(i, j int) bool {return tasks[i][0] < tasks[j][0]})
    taskQueue := heapByProcessTime{}
    curTime := 0
    ans := make([]int, 0)
    index := 0
    for index < len(tasks) || len(taskQueue) != 0 {
        // 将enqueueTime小于等于cur的task加入队列
        for index < len(tasks) && tasks[index][0] <= curTime {
            heap.Push(&taskQueue, pair{tasks[index][2], tasks[index][1]})
            index ++
        }

        // 从队列中取出一个任务,将id加入结果,更新任务结束时间cur
        if len(taskQueue) != 0 {
            task := heap.Pop(&taskQueue).(pair)
            ans = append(ans, task.i)
            curTime = curTime + task.t
        } else {
            // 队列空闲了,时间跳转到下一个任务入队列时间
            curTime = tasks[index][0]
        }
        
    }

    return ans
}


// 保存task id和processingTime
type pair struct{i int; t int}

type heapByProcessTime []pair
func (h heapByProcessTime) Less(i, j int) bool {
    if h[i].t == h[j].t {
        return h[i].i < h[j].i
    }
    return h[i].t < h[j].t
    }
func (h heapByProcessTime) Swap(i, j int)  {h[i], h[j] = h[j], h[i]}
func (h heapByProcessTime) Len() int {return len(h)}
func (h *heapByProcessTime) Push(x interface{}) {
    *h = append(*h, x.(pair))
}
func (h *heapByProcessTime) Pop() interface{} {
    old := *h
    n := len(old)
    x := old[n - 1]
    *h = old[:n - 1]
    return x
}