Problem Description
The task is to design a task management system that supports adding tasks, modifying their priority, removing tasks, and executing the highest priority task. Each task is associated with a user. When executing, if multiple tasks share the highest priority, the task with the highest taskId should be executed and removed from the system.
Key Insights
- Use a hash map (dictionary) to map each taskId to its corresponding userId and priority.
- Use a max-heap (priority queue) to efficiently extract the task with the highest priority and, in case of a tie, the highest taskId.
- Handle updates (edit and remove) by marking obsolete entries. Lazy deletion from the heap is necessary, as direct random-access update is non-trivial in heap structures.
- Each operation should work in logarithmic time relative to the number of tasks.
Space and Time Complexity
Time Complexity:
- add: O(log n) due to heap insertion
- edit: O(log n) for re-insertion in the heap (lazy deletion of old value)
- rmv: O(1) for deletion from the hash map, O(log n) amortized during execTop due to lazy removal
- execTop: O(log n) average per removal (may require several heap pops if encountering stale entries)
Space Complexity:
- O(n) for storing tasks in both the hash map and the heap.
Solution
We maintain two main data structures:
- Hash Map (e.g., map): This maps each taskId to a tuple (userId, priority). It allows constant time lookups for modifications and removals.
- Max-Heap (priority queue): Each entry is a tuple (priority, taskId) where higher priority and higher taskId make an element come out first. Since Python's heap is a min-heap by default, we store negative priority and negative taskId values. In languages like C++ or Java, use custom comparators.
For update operations (edit and remove), instead of directly updating the heap, we update the hash map and add new entries to the heap (when editing). During execution (execTop), we pop from the heap until we find an entry that matches the current values in the hash map (i.e., not stale) or the heap is empty.