|
| 1 | +/** |
| 2 | + * 3408. Design Task Manager |
| 3 | + * |
| 4 | + * LeetCode Link: https://leetcode.com/problems/design-task-manager/ |
| 5 | + * |
| 6 | + * Description: |
| 7 | + * You are asked to design a task manager that supports: |
| 8 | + * - add(userId, taskId, priority) |
| 9 | + * - edit(taskId, newPriority) |
| 10 | + * - rmv(taskId) |
| 11 | + * - execTop() |
| 12 | + * |
| 13 | + * Rules: |
| 14 | + * - execTop() always executes the task with the highest priority. |
| 15 | + * - If multiple tasks have the same priority, the one with the highest taskId is chosen. |
| 16 | + * - execTop() should return the userId of the executed task. |
| 17 | + * |
| 18 | + * ----------------------------------------------------------- |
| 19 | + * Approach: |
| 20 | + * We use a combination of: |
| 21 | + * 1. A HashMap<Integer, Task> to keep track of taskId -> Task info. |
| 22 | + * 2. A TreeSet<Task> with a custom comparator to order tasks by: |
| 23 | + * - Higher priority first |
| 24 | + * - If tie, higher taskId first |
| 25 | + * - Tie breaker: smaller userId (to keep comparator stable) |
| 26 | + * |
| 27 | + * Operations: |
| 28 | + * - add: Insert into both HashMap and TreeSet. |
| 29 | + * - edit: Remove old task from TreeSet, update priority, reinsert. |
| 30 | + * - rmv: Remove task from both structures. |
| 31 | + * - execTop: Poll the first task from TreeSet (highest priority), return its userId. |
| 32 | + * |
| 33 | + * ----------------------------------------------------------- |
| 34 | + * Complexity: |
| 35 | + * - add: O(log n) due to TreeSet |
| 36 | + * - edit: O(log n) due to remove + add in TreeSet |
| 37 | + * - rmv: O(log n) |
| 38 | + * - execTop: O(log n) |
| 39 | + * Space: O(n) for storing all tasks. |
| 40 | + */ |
| 41 | + |
| 42 | +import java.util.*; |
| 43 | + |
| 44 | +class Task { |
| 45 | + int userId; |
| 46 | + int taskId; |
| 47 | + int priority; |
| 48 | + Task(int u, int t, int p) { |
| 49 | + userId = u; |
| 50 | + taskId = t; |
| 51 | + priority = p; |
| 52 | + } |
| 53 | +} |
| 54 | + |
| 55 | +class TaskManager { |
| 56 | + |
| 57 | + private Map<Integer, Task> taskInfo = new HashMap<>(); |
| 58 | + private TreeSet<Task> taskSet; |
| 59 | + |
| 60 | + public TaskManager(List<List<Integer>> tasks) { |
| 61 | + taskSet = new TreeSet<>((a, b) -> { |
| 62 | + if (a.priority != b.priority) { |
| 63 | + return Integer.compare(b.priority, a.priority); // higher priority first |
| 64 | + } |
| 65 | + if (a.taskId != b.taskId) { |
| 66 | + return Integer.compare(b.taskId, a.taskId); // higher taskId first |
| 67 | + } |
| 68 | + return Integer.compare(a.userId, b.userId); // tie breaker for stability |
| 69 | + }); |
| 70 | + |
| 71 | + for (List<Integer> t : tasks) { |
| 72 | + add(t.get(0), t.get(1), t.get(2)); |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + public void add(int userId, int taskId, int priority) { |
| 77 | + Task task = new Task(userId, taskId, priority); |
| 78 | + taskInfo.put(taskId, task); |
| 79 | + taskSet.add(task); |
| 80 | + } |
| 81 | + |
| 82 | + public void edit(int taskId, int newPriority) { |
| 83 | + Task old = taskInfo.get(taskId); |
| 84 | + if (old == null) return; |
| 85 | + taskSet.remove(old); |
| 86 | + Task updated = new Task(old.userId, taskId, newPriority); |
| 87 | + taskInfo.put(taskId, updated); |
| 88 | + taskSet.add(updated); |
| 89 | + } |
| 90 | + |
| 91 | + public void rmv(int taskId) { |
| 92 | + Task old = taskInfo.get(taskId); |
| 93 | + if (old == null) return; |
| 94 | + taskSet.remove(old); |
| 95 | + taskInfo.remove(taskId); |
| 96 | + } |
| 97 | + |
| 98 | + public int execTop() { |
| 99 | + if (taskSet.isEmpty()) return -1; |
| 100 | + Task top = taskSet.first(); // highest priority, highest taskId |
| 101 | + taskSet.remove(top); |
| 102 | + taskInfo.remove(top.taskId); |
| 103 | + return top.userId; |
| 104 | + } |
| 105 | +} |
0 commit comments