1834. Single-Threaded CPU

這題其實有點算實作題, 題目有提到

the CPU will choose the one with the shortest processing time. 
=> pq (small processingTimei, smallest index)

所以要用 pq, 因為要對 time, index 做排序, 所以做一個 class 出來存會是比較漂亮的作法,

Queue<Task> queue = new PriorityQueue<>((a,b) -> {
            return a.processingTime == b.processingTime ? a.index - b.index : a.processingTime - b.processingTime;
        });

因為是照時間順序來放入 pq, 所以當然開始時間要先排序

Arrays.sort(jobs, (a,b) -> a.enqueueTime - b.enqueueTime);

比較不好設計的部分是, 如何按照 啟動時間 入 pq 呢?

from the name enqueueTime => hint us can add to queue

重點要有個 curTime 來記錄目前時間到哪裡了, pq 是空的時候, 會給予初值(第一個job 的起始時間)

其他 pq 有元素時, 當然就是更新結果和更新 curTime (加上 processingTime, 因為這是一個 single thread 的 CPU, 一次做一件事)

from array to queue

也維持了一個 runIdx 來讀下個 job, 條件是 起始時間 <= curTime

while()...這裏

如此就可以把符合起始時間 的job 入 pq

        int[] order = new int[n];
        int orderIdx = 0;
        int runIdx = 0;
        int curTime = 0;
        while (orderIdx < n) {
            
            while (runIdx < n && jobs[runIdx].enqueueTime <= curTime) {
                queue.offer(jobs[runIdx]);
                runIdx++;
            }
            // when no data in queue, curTime needs to refresh
            if (queue.isEmpty()) {
                curTime = jobs[runIdx].enqueueTime;
            } else {
                Task cur = queue.poll();
                order[orderIdx++] = cur.index;
                curTime += cur.processingTime;
            }
        }
        return order;

T: O(nlogn)
S: O(n)
class Solution {
    class Task {
        int index;
        int enqueueTime;
        int processingTime;
        Task(int index,
             int enqueueTime,
             int processingTime) {
            
            this.index = index;
            this.enqueueTime = enqueueTime;
            this.processingTime = processingTime;
        }
    }
    public int[] getOrder(int[][] tasks) {
        int n = tasks.length;
        Task[] jobs = new Task[n]; 
        for (int i = 0; i < n; i++) {
            jobs[i] = new Task(i, tasks[i][0], tasks[i][1]);
        }
        Arrays.sort(jobs, (a,b) -> a.enqueueTime - b.enqueueTime);
        
        Queue<Task> queue = new PriorityQueue<>((a,b) -> {
            return a.processingTime == b.processingTime ? a.index - b.index : a.processingTime - b.processingTime;
        });
        
        int[] order = new int[n];
        int orderIdx = 0;
        int runIdx = 0;
        int curTime = 0;
        while (orderIdx < n) {
            
            while (runIdx < n && jobs[runIdx].enqueueTime <= curTime) {
                queue.offer(jobs[runIdx]);
                runIdx++;
            }
            // when no data in queue, curTime needs to refresh
            if (queue.isEmpty()) {
                curTime = jobs[runIdx].enqueueTime;
            } else {
                Task cur = queue.poll();
                order[orderIdx++] = cur.index;
                curTime += cur.processingTime;
            }
        }
        return order;
    }
}

/*
tasks[i] = [enqueueTimei, processingTimei]

ith task
process at enqueueTimei, needs processingTimei


the CPU will choose the one with the shortest processing time. 
=> pq (small processingTimei, smallest index)

finished entire task


Return the order in which the CPU will process the tasks. (index)


[[1,2],[2,4],[3,2],[4,1]]


1. build task class
2. define pq

curTime = 0;
3. while (orderId < n) {
    while (runId < n && eTime <= curTime) {
        add to heap
        runId++
    }
    if (heap is empty) {
        init curTime = task[runId].eTime
    }
    
    heap pop, get cur task
    add to result[orderId++]
    curTime += cur task.proTime
    
}

T: O(nlogn)
S: O(n)
*/

Last updated

Was this helpful?