Welcome to Subscribe On Youtube
Formatted question description: https://leetcode.ca/all/1834.html
1834. Single-Threaded CPU
Level
Medium
Description
You are given n
tasks labeled from 0
to n - 1
represented by a 2D integer array tasks
, where tasks[i] = [enqueueTime_i, processingTime_i]
means that the ith task will be available to process at enqueueTime_i
and will take processingTime_i
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.
Example 1:
Input: tasks = [[1,2],[2,4],[3,2],[4,1]]
Output: [0,2,3,1]
Explanation: The events go as follows:
- At time = 1, task 0 is available to process. Available tasks = {0}.
- Also at time = 1, the idle CPU starts processing task 0. Available tasks = {}.
- At time = 2, task 1 is available to process. Available tasks = {1}.
- At time = 3, task 2 is available to process. Available tasks = {1, 2}.
- Also at time = 3, the CPU finishes task 0 and starts processing task 2 as it is the shortest. Available tasks = {1}.
- At time = 4, task 3 is available to process. Available tasks = {1, 3}.
- At time = 5, the CPU finishes task 2 and starts processing task 3 as it is the shortest. Available tasks = {1}.
- At time = 6, the CPU finishes task 3 and starts processing task 1. Available tasks = {}.
- At time = 10, the CPU finishes task 1 and becomes idle.
Example 2:
Input: tasks = [[7,10],[7,12],[7,5],[7,4],[7,2]]
Output: [4,3,2,0,1]
Explanation: The events go as follows:
- At time = 7, all the tasks become available. Available tasks = {0,1,2,3,4}.
- Also at time = 7, the idle CPU starts processing task 4. Available tasks = {0,1,2,3}.
- At time = 9, the CPU finishes task 4 and starts processing task 3. Available tasks = {0,1,2}.
- At time = 13, the CPU finishes task 3 and starts processing task 2. Available tasks = {0,1}.
- At time = 18, the CPU finishes task 2 and starts processing task 0. Available tasks = {1}.
- At time = 28, the CPU finishes task 0 and starts processing task 1. Available tasks = {}.
- At time = 40, the CPU finishes task 1 and becomes idle.
Constraints:
tasks.length == n
1 <= n <= 10^5
1 <= enqueueTimei, processingTimei <= 10^9
Solution
For each task, store its index as well. Then sort the tasks according to the enqueue times. Use a priority queue to store the tasks, where the task with the shortest processing time and the smallest index in case of a tie is polled first.
Loop over the sorted tasks. For each task, if the task’s enqueue time is before or the same as the current time, or the priority queue is empty, offer it to the priority queue. Otherwise, poll a task from the priority queue, put the task’s index to the result array, and update the current time accordingly.
After the tasks are looped over, while the priority queue is not empty, poll the tasks from the priority queue, put the task’s index to the result array, and update the current time accordingly.
Finally, return the result array.
-
class Solution { public int[] getOrder(int[][] tasks) { int n = tasks.length; long[][] newTasks = new long[n][3]; for (int i = 0; i < n; i++) { newTasks[i][0] = (long) tasks[i][0]; newTasks[i][1] = (long) tasks[i][1]; newTasks[i][2] = (long) i; } Arrays.sort(newTasks, new Comparator<long[]>() { public int compare(long[] task1, long[] task2) { if (task1[0] == task2[0]) return 0; else if (task1[0] > task2[0]) return 1; else return -1; } }); int[] order = new int[n]; PriorityQueue<long[]> priorityQueue = new PriorityQueue<long[]>(new Comparator<long[]>() { public int compare(long[] task1, long[] task2) { if (task1[1] != task2[1]) return task1[1] > task2[1] ? 1 : -1; else return task1[2] > task2[2] ? 1 : -1; } }); int index = 0, orderIndex = 0; long curTime = newTasks[index][0]; while (index < n) { long[] task = newTasks[index]; if (task[0] <= curTime || priorityQueue.isEmpty()) { priorityQueue.offer(task); curTime = Math.max(curTime, task[0]); index++; } else { long[] nextTask = priorityQueue.poll(); order[orderIndex++] = (int) nextTask[2]; curTime = Math.max(curTime + nextTask[1], nextTask[0] + nextTask[1]); } } while (!priorityQueue.isEmpty()) { long[] nextTask = priorityQueue.poll(); order[orderIndex++] = (int) nextTask[2]; curTime = Math.max(curTime + nextTask[1], nextTask[0] + nextTask[1]); } return order; } } ############ class Solution { public int[] getOrder(int[][] tasks) { int n = tasks.length; int[][] ts = new int[n][3]; for (int i = 0; i < n; ++i) { ts[i] = new int[] {tasks[i][0], tasks[i][1], i}; } Arrays.sort(ts, (a, b) -> a[0] - b[0]); int[] ans = new int[n]; PriorityQueue<int[]> q = new PriorityQueue<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]); int i = 0, t = 0, k = 0; while (!q.isEmpty() || i < n) { if (q.isEmpty()) { t = Math.max(t, ts[i][0]); } while (i < n && ts[i][0] <= t) { q.offer(new int[] {ts[i][1], ts[i][2]}); ++i; } var p = q.poll(); ans[k++] = p[1]; t += p[0]; } return ans; } }
-
class Solution: def getOrder(self, tasks: List[List[int]]) -> List[int]: for i, task in enumerate(tasks): task.append(i) tasks.sort() ans = [] q = [] n = len(tasks) i = t = 0 while q or i < n: if not q: t = max(t, tasks[i][0]) while i < n and tasks[i][0] <= t: heappush(q, (tasks[i][1], tasks[i][2])) i += 1 pt, j = heappop(q) ans.append(j) t += pt return ans ############ # 1834. Single-Threaded CPU # https://leetcode.com/problems/single-threaded-cpu/ class Solution: def getOrder(self, tasks: List[List[int]]) -> List[int]: n = len(tasks) available = collections.defaultdict(list) t = float('inf') for i, (a,b) in enumerate(tasks): available[a].append((b, i)) t = min(t, a) res = [] heap = [] ki = 0 kn = len(available) keys = list(available.keys()) keys.sort() while len(res) != n: isUpdated = False while ki < kn and keys[ki] <= t: new = available[keys[ki]] for at in new: heap.append(at) isUpdated = True ki += 1 if isUpdated: heapq.heapify(heap) if ki == kn: while heap: time, i = heapq.heappop(heap) res.append(i) else: if heap: time, i = heapq.heappop(heap) t += time res.append(i) else: t = keys[ki] return res
-
class Solution { public: vector<int> getOrder(vector<vector<int>>& tasks) { int n = 0; for (auto& task : tasks) task.push_back(n++); sort(tasks.begin(), tasks.end()); using pii = pair<int, int>; priority_queue<pii, vector<pii>, greater<pii>> q; int i = 0; long long t = 0; vector<int> ans; while (!q.empty() || i < n) { if (q.empty()) t = max(t, (long long) tasks[i][0]); while (i < n && tasks[i][0] <= t) { q.push({tasks[i][1], tasks[i][2]}); ++i; } auto [pt, j] = q.top(); q.pop(); ans.push_back(j); t += pt; } return ans; } };
-
func getOrder(tasks [][]int) (ans []int) { 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] }) q := hp{} i, t, n := 0, 0, len(tasks) for len(q) > 0 || i < n { if len(q) == 0 { t = max(t, tasks[i][0]) } for i < n && tasks[i][0] <= t { heap.Push(&q, pair{tasks[i][1], tasks[i][2]}) i++ } p := heap.Pop(&q).(pair) ans = append(ans, p.i) t += p.t } return } func max(a, b int) int { if a > b { return a } return b } type pair struct{ t, i int } type hp []pair func (h hp) Len() int { return len(h) } func (h hp) Less(i, j int) bool { return h[i].t < h[j].t || (h[i].t == h[j].t && h[i].i < h[j].i) } func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *hp) Push(v interface{}) { *h = append(*h, v.(pair)) } func (h *hp) Pop() interface{} { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }