3408. Design Task Manager
Problem Description
This problem asks you to implement a task management system that can handle multiple users and their tasks. Each task has a priority level, and the system needs to support several operations.
The TaskManager
class needs to support the following operations:
-
Initialization: Create the task manager with an initial list of tasks. Each task is represented as
[userId, taskId, priority]
. -
Add a task: Add a new task to a specific user with
add(userId, taskId, priority)
. ThetaskId
is guaranteed to be unique (not already in the system). -
Edit a task: Change the priority of an existing task with
edit(taskId, newPriority)
. ThetaskId
is guaranteed to exist in the system. -
Remove a task: Delete a task from the system with
rmv(taskId)
. ThetaskId
is guaranteed to exist. -
Execute top priority task: Execute and remove the highest priority task across all users with
execTop()
. If multiple tasks have the same highest priority, choose the one with the highesttaskId
. Return theuserId
of the executed task, or -1 if no tasks exist.
The solution uses two data structures:
- A dictionary
d
that maps eachtaskId
to a tuple of(userId, priority)
- A
SortedList
that maintains tasks sorted by priority and taskId
The key insight is storing tasks as (-priority, -taskId)
in the sorted list. This ensures that:
- Higher priorities come first (since we negate the priority)
- Among tasks with the same priority, higher taskIds come first (since we negate the taskId)
When executing the top task, the system simply pops the first element from the sorted list, retrieves the corresponding user information from the dictionary, and returns the userId.
Intuition
The core challenge is maintaining tasks in a way that allows us to quickly find and execute the highest priority task while also supporting efficient updates and deletions.
Let's think about what data we need to track:
- For each task, we need to know which user owns it and its priority
- We need to find the highest priority task quickly
- When priorities are tied, we need the highest taskId
A natural first thought might be to use a heap or priority queue. However, standard heaps don't support efficient arbitrary deletions or updates - we'd need to search through the entire heap to find a specific taskId for editing or removal.
This leads us to consider maintaining two separate data structures:
- A mapping to quickly look up task information by taskId
- A sorted structure to maintain priority ordering
For the mapping, a dictionary is perfect - it gives us O(1) access to any task's information using its taskId as the key. We store (userId, priority)
as the value.
For maintaining sorted order, we need a structure that supports:
- Insertion in sorted order
- Removal of arbitrary elements
- Access to the maximum element
A SortedList
(balanced binary search tree) fits perfectly, providing O(log n) operations for all these needs.
The clever trick is how we store elements in the sorted list. Since we want the highest priority first but Python's sorted structures maintain ascending order, we store negative priorities (-priority)
. Similarly, when priorities are equal, we want the highest taskId first, so we also negate the taskId (-taskId)
. This transforms our "find maximum" problem into a "find minimum" problem, which naturally aligns with the sorted order.
By maintaining these two synchronized data structures, we achieve efficient operations: O(log n) for add, edit, and remove operations, and O(log n) for executing the top task.
Learn more about Heap (Priority Queue) patterns.
Solution Approach
The solution uses two synchronized data structures to efficiently manage tasks:
- Dictionary
d
: MapstaskId
to(userId, priority)
for O(1) lookups - SortedList
st
: Maintains tasks in sorted order by(-priority, -taskId)
Implementation Details:
Initialization (__init__
):
def __init__(self, tasks: List[List[int]]):
self.d = {}
self.st = SortedList()
for task in tasks:
self.add(*task)
- Initialize empty dictionary and sorted list
- Use the
add
method to process each initial task
Adding a Task (add
):
def add(self, userId: int, taskId: int, priority: int) -> None:
self.d[taskId] = (userId, priority)
self.st.add((-priority, -taskId))
- Store task information in dictionary with
taskId
as key - Add
(-priority, -taskId)
tuple to sorted list to maintain proper ordering
Editing Task Priority (edit
):
def edit(self, taskId: int, newPriority: int) -> None:
userId, priority = self.d[taskId]
self.st.discard((-priority, -taskId))
self.d[taskId] = (userId, newPriority)
self.st.add((-newPriority, -taskId))
- Retrieve current user and priority from dictionary
- Remove old entry from sorted list using
discard
(won't raise error if not found) - Update dictionary with new priority
- Add new entry to sorted list with updated priority
Removing a Task (rmv
):
def rmv(self, taskId: int) -> None:
_, priority = self.d[taskId]
self.d.pop(taskId)
self.st.remove((-priority, -taskId))
- Get priority from dictionary (userId not needed)
- Remove from dictionary using
pop
- Remove from sorted list using
remove
Executing Top Priority Task (execTop
):
def execTop(self) -> int:
if not self.st:
return -1
taskId = -self.st.pop(0)[1]
userId, _ = self.d[taskId]
self.d.pop(taskId)
return userId
- Check if sorted list is empty, return -1 if no tasks
- Pop the first element (highest priority due to negative values)
- Extract
taskId
by negating the second element of the tuple - Get
userId
from dictionary - Remove task from dictionary
- Return the
userId
Time Complexity:
add
: O(log n) for sorted list insertionedit
: O(log n) for removal and insertion in sorted listrmv
: O(log n) for sorted list removalexecTop
: O(log n) for popping from sorted list- Space: O(n) for storing n tasks
The negative value trick (-priority, -taskId)
ensures that the sorted list maintains tasks in descending order of priority and taskId, making the first element always the correct one to execute.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example to illustrate how the solution works.
Initial Setup:
tasks = [[1, 101, 3], [2, 102, 5], [1, 103, 3]] tm = TaskManager(tasks)
After initialization:
- Dictionary
d
:{101: (1, 3), 102: (2, 5), 103: (1, 3)}
- SortedList
st
:[(-5, -102), (-3, -103), (-3, -101)]
Notice how the sorted list orders tasks:
- Task 102 with priority 5 comes first (stored as -5)
- Tasks 101 and 103 both have priority 3, but 103 has higher taskId, so (-3, -103) comes before (-3, -101)
Operation 1: Execute top priority task
result = tm.execTop() # Returns 2
- The first element in sorted list is
(-5, -102)
- Extract taskId:
-(-102) = 102
- Look up in dictionary:
d[102] = (2, 5)
, so userId = 2 - Remove task 102 from both structures
- After:
d = {101: (1, 3), 103: (1, 3)}
,st = [(-3, -103), (-3, -101)]
Operation 2: Add a new task
tm.add(3, 104, 3)
- Add to dictionary:
d[104] = (3, 3)
- Add to sorted list:
(-3, -104)
- After:
d = {101: (1, 3), 103: (1, 3), 104: (3, 3)}
,st = [(-3, -104), (-3, -103), (-3, -101)]
- Note: Task 104 is now first among priority-3 tasks due to highest taskId
Operation 3: Edit task priority
tm.edit(101, 7)
- Current info:
d[101] = (1, 3)
- Remove
(-3, -101)
from sorted list - Update dictionary:
d[101] = (1, 7)
- Add
(-7, -101)
to sorted list - After:
d = {101: (1, 7), 103: (1, 3), 104: (3, 3)}
,st = [(-7, -101), (-3, -104), (-3, -103)]
- Task 101 is now the highest priority task
Operation 4: Execute top priority task again
result = tm.execTop() # Returns 1
- Pop
(-7, -101)
from sorted list - taskId = 101, userId = 1
- After:
d = {103: (1, 3), 104: (3, 3)}
,st = [(-3, -104), (-3, -103)]
This example demonstrates how the negative value storage ensures correct priority ordering and how the two data structures work together to maintain efficient operations.
Solution Implementation
1from typing import List
2from sortedcontainers import SortedList
3
4
5class TaskManager:
6 def __init__(self, tasks: List[List[int]]):
7 """
8 Initialize the TaskManager with a list of tasks.
9 Each task is represented as [userId, taskId, priority].
10 """
11 # Dictionary to store task information: taskId -> (userId, priority)
12 self.task_info = {}
13
14 # SortedList to maintain tasks ordered by priority (highest first) and taskId (highest first)
15 # Using negative values to achieve descending order
16 self.priority_queue = SortedList()
17
18 # Add all initial tasks
19 for task in tasks:
20 self.add(task[0], task[1], task[2])
21
22 def add(self, userId: int, taskId: int, priority: int) -> None:
23 """
24 Add a new task to the system.
25
26 Args:
27 userId: ID of the user who owns the task
28 taskId: Unique identifier for the task
29 priority: Priority level of the task (higher value = higher priority)
30 """
31 # Store task information in dictionary
32 self.task_info[taskId] = (userId, priority)
33
34 # Add to sorted list with negative values for descending order
35 # Negative priority ensures higher priorities come first
36 # Negative taskId ensures higher taskIds come first when priorities are equal
37 self.priority_queue.add((-priority, -taskId))
38
39 def edit(self, taskId: int, newPriority: int) -> None:
40 """
41 Edit the priority of an existing task.
42
43 Args:
44 taskId: ID of the task to edit
45 newPriority: New priority value for the task
46 """
47 # Retrieve current task information
48 user_id, old_priority = self.task_info[taskId]
49
50 # Remove old entry from sorted list
51 self.priority_queue.discard((-old_priority, -taskId))
52
53 # Update task information with new priority
54 self.task_info[taskId] = (user_id, newPriority)
55
56 # Add updated entry to sorted list
57 self.priority_queue.add((-newPriority, -taskId))
58
59 def rmv(self, taskId: int) -> None:
60 """
61 Remove a task from the system.
62
63 Args:
64 taskId: ID of the task to remove
65 """
66 # Retrieve task priority for removal from sorted list
67 _, priority = self.task_info[taskId]
68
69 # Remove task from dictionary
70 self.task_info.pop(taskId)
71
72 # Remove task from sorted list
73 self.priority_queue.remove((-priority, -taskId))
74
75 def execTop(self) -> int:
76 """
77 Execute the highest priority task and remove it from the system.
78
79 Returns:
80 The userId of the executed task, or -1 if no tasks exist
81 """
82 # Check if there are any tasks to execute
83 if not self.priority_queue:
84 return -1
85
86 # Pop the highest priority task (first element in sorted list)
87 # Extract taskId by negating the second element of the tuple
88 task_id = -self.priority_queue.pop(0)[1]
89
90 # Get the userId of the task owner
91 user_id, _ = self.task_info[task_id]
92
93 # Remove task from dictionary
94 self.task_info.pop(task_id)
95
96 return user_id
97
98
99# Your TaskManager object will be instantiated and called as such:
100# obj = TaskManager(tasks)
101# obj.add(userId, taskId, priority)
102# obj.edit(taskId, newPriority)
103# obj.rmv(taskId)
104# param_4 = obj.execTop()
105
1class TaskManager {
2 // Map to store taskId -> [userId, priority]
3 private final Map<Integer, int[]> taskMap = new HashMap<>();
4
5 // TreeSet to maintain tasks sorted by priority (descending) and taskId (descending)
6 // Format: [priority, taskId]
7 private final TreeSet<int[]> priorityQueue = new TreeSet<>((a, b) -> {
8 // If priorities are equal, sort by taskId in descending order
9 if (a[0] == b[0]) {
10 return b[1] - a[1];
11 }
12 // Sort by priority in descending order (higher priority first)
13 return b[0] - a[0];
14 });
15
16 /**
17 * Constructor to initialize the TaskManager with a list of tasks
18 * @param tasks List of tasks where each task contains [userId, taskId, priority]
19 */
20 public TaskManager(List<List<Integer>> tasks) {
21 for (List<Integer> task : tasks) {
22 add(task.get(0), task.get(1), task.get(2));
23 }
24 }
25
26 /**
27 * Add a new task to the system
28 * @param userId The user who owns the task
29 * @param taskId The unique identifier for the task
30 * @param priority The priority level of the task
31 */
32 public void add(int userId, int taskId, int priority) {
33 // Store task information in the map
34 taskMap.put(taskId, new int[] {userId, priority});
35
36 // Add task to the priority queue
37 priorityQueue.add(new int[] {priority, taskId});
38 }
39
40 /**
41 * Edit the priority of an existing task
42 * @param taskId The task to be edited
43 * @param newPriority The new priority value for the task
44 */
45 public void edit(int taskId, int newPriority) {
46 // Retrieve existing task information
47 int[] taskInfo = taskMap.get(taskId);
48 int userId = taskInfo[0];
49 int oldPriority = taskInfo[1];
50
51 // Remove old entry from priority queue
52 priorityQueue.remove(new int[] {oldPriority, taskId});
53
54 // Add updated entry to priority queue
55 priorityQueue.add(new int[] {newPriority, taskId});
56
57 // Update task information in the map
58 taskMap.put(taskId, new int[] {userId, newPriority});
59 }
60
61 /**
62 * Remove a task from the system
63 * @param taskId The task to be removed
64 */
65 public void rmv(int taskId) {
66 // Remove task from map and get its information
67 int[] taskInfo = taskMap.remove(taskId);
68 int priority = taskInfo[1];
69
70 // Remove task from priority queue
71 priorityQueue.remove(new int[] {priority, taskId});
72 }
73
74 /**
75 * Execute the task with the highest priority and return the userId
76 * @return The userId of the executed task, or -1 if no tasks exist
77 */
78 public int execTop() {
79 // Check if there are any tasks to execute
80 if (priorityQueue.isEmpty()) {
81 return -1;
82 }
83
84 // Remove and get the highest priority task
85 int[] topTask = priorityQueue.pollFirst();
86 int taskId = topTask[1];
87
88 // Remove task from map and get user information
89 int[] taskInfo = taskMap.remove(taskId);
90 int userId = taskInfo[0];
91
92 return userId;
93 }
94}
95
96/**
97 * Your TaskManager object will be instantiated and called as such:
98 * TaskManager obj = new TaskManager(tasks);
99 * obj.add(userId,taskId,priority);
100 * obj.edit(taskId,newPriority);
101 * obj.rmv(taskId);
102 * int param_4 = obj.execTop();
103 */
104
1class TaskManager {
2private:
3 // Map: taskId -> (userId, priority)
4 unordered_map<int, pair<int, int>> taskMap;
5
6 // Set to maintain tasks sorted by priority (descending) and taskId (descending)
7 // Stores pairs of (-priority, -taskId) for automatic sorting
8 set<pair<int, int>> prioritySet;
9
10public:
11 /**
12 * Constructor: Initialize the task manager with initial tasks
13 * @param tasks: Vector of tasks where each task is [userId, taskId, priority]
14 */
15 TaskManager(vector<vector<int>>& tasks) {
16 for (const auto& task : tasks) {
17 add(task[0], task[1], task[2]);
18 }
19 }
20
21 /**
22 * Add a new task to the system
23 * @param userId: The user who owns the task
24 * @param taskId: Unique identifier for the task
25 * @param priority: Priority level of the task
26 */
27 void add(int userId, int taskId, int priority) {
28 // Store task information in the map
29 taskMap[taskId] = {userId, priority};
30
31 // Insert into set with negative values for descending order
32 // Higher priority and higher taskId will come first
33 prioritySet.insert({-priority, -taskId});
34 }
35
36 /**
37 * Edit the priority of an existing task
38 * @param taskId: The task to edit
39 * @param newPriority: The new priority value
40 */
41 void edit(int taskId, int newPriority) {
42 // Get current task information
43 auto [userId, oldPriority] = taskMap[taskId];
44
45 // Remove old entry from the priority set
46 prioritySet.erase({-oldPriority, -taskId});
47
48 // Insert new entry with updated priority
49 prioritySet.insert({-newPriority, -taskId});
50
51 // Update the task map with new priority
52 taskMap[taskId] = {userId, newPriority};
53 }
54
55 /**
56 * Remove a task from the system
57 * @param taskId: The task to remove
58 */
59 void rmv(int taskId) {
60 // Get task information before removal
61 auto [userId, priority] = taskMap[taskId];
62
63 // Remove from priority set
64 prioritySet.erase({-priority, -taskId});
65
66 // Remove from task map
67 taskMap.erase(taskId);
68 }
69
70 /**
71 * Execute the highest priority task
72 * @return: The userId of the executed task, or -1 if no tasks exist
73 */
74 int execTop() {
75 // Check if there are any tasks to execute
76 if (prioritySet.empty()) {
77 return -1;
78 }
79
80 // Get the highest priority task (first element in set)
81 auto topTask = *prioritySet.begin();
82 prioritySet.erase(prioritySet.begin());
83
84 // Extract taskId (negate to get original value)
85 int taskId = -topTask.second;
86
87 // Get userId from the task map
88 int userId = taskMap[taskId].first;
89
90 // Remove task from map
91 taskMap.erase(taskId);
92
93 return userId;
94 }
95};
96
97/**
98 * Your TaskManager object will be instantiated and called as such:
99 * TaskManager* obj = new TaskManager(tasks);
100 * obj->add(userId,taskId,priority);
101 * obj->edit(taskId,newPriority);
102 * obj->rmv(taskId);
103 * int param_4 = obj->execTop();
104 */
105
1// Map: taskId -> [userId, priority]
2const taskMap: Map<number, [number, number]> = new Map();
3
4// Array to maintain tasks sorted by priority (descending) and taskId (descending)
5// Stores tuples of [priority, taskId]
6let priorityArray: [number, number][] = [];
7
8/**
9 * Initialize the task manager with initial tasks
10 * @param tasks - Array of tasks where each task is [userId, taskId, priority]
11 */
12function TaskManager(tasks: number[][]): void {
13 // Clear existing data
14 taskMap.clear();
15 priorityArray = [];
16
17 // Add all initial tasks
18 for (const task of tasks) {
19 add(task[0], task[1], task[2]);
20 }
21}
22
23/**
24 * Add a new task to the system
25 * @param userId - The user who owns the task
26 * @param taskId - Unique identifier for the task
27 * @param priority - Priority level of the task
28 */
29function add(userId: number, taskId: number, priority: number): void {
30 // Store task information in the map
31 taskMap.set(taskId, [userId, priority]);
32
33 // Add to priority array
34 priorityArray.push([priority, taskId]);
35
36 // Sort array to maintain order: higher priority first, then higher taskId first
37 priorityArray.sort((a, b) => {
38 if (a[0] !== b[0]) {
39 return b[0] - a[0]; // Descending by priority
40 }
41 return b[1] - a[1]; // Descending by taskId
42 });
43}
44
45/**
46 * Edit the priority of an existing task
47 * @param taskId - The task to edit
48 * @param newPriority - The new priority value
49 */
50function edit(taskId: number, newPriority: number): void {
51 // Get current task information
52 const taskInfo = taskMap.get(taskId);
53 if (!taskInfo) return;
54
55 const [userId, oldPriority] = taskInfo;
56
57 // Find and remove the old entry from priority array
58 const indexToRemove = priorityArray.findIndex(
59 item => item[0] === oldPriority && item[1] === taskId
60 );
61 if (indexToRemove !== -1) {
62 priorityArray.splice(indexToRemove, 1);
63 }
64
65 // Update the task map with new priority
66 taskMap.set(taskId, [userId, newPriority]);
67
68 // Add new entry and re-sort
69 priorityArray.push([newPriority, taskId]);
70 priorityArray.sort((a, b) => {
71 if (a[0] !== b[0]) {
72 return b[0] - a[0]; // Descending by priority
73 }
74 return b[1] - a[1]; // Descending by taskId
75 });
76}
77
78/**
79 * Remove a task from the system
80 * @param taskId - The task to remove
81 */
82function rmv(taskId: number): void {
83 // Get task information before removal
84 const taskInfo = taskMap.get(taskId);
85 if (!taskInfo) return;
86
87 const [userId, priority] = taskInfo;
88
89 // Find and remove from priority array
90 const indexToRemove = priorityArray.findIndex(
91 item => item[0] === priority && item[1] === taskId
92 );
93 if (indexToRemove !== -1) {
94 priorityArray.splice(indexToRemove, 1);
95 }
96
97 // Remove from task map
98 taskMap.delete(taskId);
99}
100
101/**
102 * Execute the highest priority task
103 * @returns The userId of the executed task, or -1 if no tasks exist
104 */
105function execTop(): number {
106 // Check if there are any tasks to execute
107 if (priorityArray.length === 0) {
108 return -1;
109 }
110
111 // Get the highest priority task (first element in array)
112 const topTask = priorityArray.shift();
113 if (!topTask) return -1;
114
115 const [priority, taskId] = topTask;
116
117 // Get userId from the task map
118 const taskInfo = taskMap.get(taskId);
119 if (!taskInfo) return -1;
120
121 const userId = taskInfo[0];
122
123 // Remove task from map
124 taskMap.delete(taskId);
125
126 return userId;
127}
128
Time and Space Complexity
Time Complexity:
-
__init__(tasks)
:O(n log n)
wheren
is the number of tasks. Each task is added to the dictionary inO(1)
and to the SortedList inO(log n)
, resulting inO(n log n)
for all tasks. -
add(userId, taskId, priority)
:O(log n)
wheren
is the current number of tasks. Dictionary insertion isO(1)
, but adding to SortedList requiresO(log n)
for maintaining sorted order. -
edit(taskId, newPriority)
:O(log n)
wheren
is the current number of tasks. The operation involves:- Dictionary lookup:
O(1)
- Discarding from SortedList:
O(log n)
for finding +O(n)
worst case for removal - Dictionary update:
O(1)
- Adding to SortedList:
O(log n)
- Overall:
O(n)
worst case, but typicallyO(log n)
in practice
- Dictionary lookup:
-
rmv(taskId)
:O(n)
worst case wheren
is the current number of tasks. The operation involves:- Dictionary lookup:
O(1)
- Dictionary deletion:
O(1)
- Removing from SortedList:
O(log n)
for finding +O(n)
for removal - Overall:
O(n)
due to theremove()
operation
- Dictionary lookup:
-
execTop()
:O(log n)
wheren
is the current number of tasks. Popping from the front of SortedList isO(log n)
, and dictionary operations areO(1)
.
Space Complexity:
- Overall space complexity:
O(n)
wheren
is the number of tasks - Dictionary
self.d
:O(n)
to store all task mappings - SortedList
self.st
:O(n)
to store all task priorities and IDs - Total auxiliary space:
O(n)
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Forgetting to Handle the Tie-Breaking Rule Correctly
Pitfall: When multiple tasks have the same priority, the problem requires choosing the one with the highest taskId
. A common mistake is to use (priority, taskId)
directly in the sorted list, which would give us the lowest taskId
when priorities are equal.
Incorrect Implementation:
# Wrong: This would select lowest taskId when priorities are equal self.priority_queue.add((-priority, taskId)) # INCORRECT!
Solution: Store both priority and taskId as negative values: (-priority, -taskId)
. This ensures that when the sorted list orders tuples, higher taskIds come first among tasks with the same priority.
2. Using remove()
Instead of discard()
in Edit Operation
Pitfall: In the edit()
method, if there's any synchronization issue or the task was already removed, using remove()
will raise a ValueError
if the element is not found.
Problematic Code:
def edit(self, taskId: int, newPriority: int) -> None:
userId, priority = self.task_info[taskId]
self.priority_queue.remove((-priority, -taskId)) # May raise ValueError!
# ...
Solution: Use discard()
which silently does nothing if the element is not present:
self.priority_queue.discard((-priority, -taskId)) # Safe operation
3. Inconsistent Data Structure Updates
Pitfall: Forgetting to update both data structures (dictionary and sorted list) in sync. For example, removing from one but not the other.
Incorrect Implementation:
def rmv(self, taskId: int) -> None:
# Forgot to get priority before removing from dictionary!
self.task_info.pop(taskId)
# Now we can't remove from sorted list because we lost the priority
self.priority_queue.remove((-priority, -taskId)) # priority is undefined!
Solution: Always retrieve necessary information before modifying any data structure:
def rmv(self, taskId: int) -> None:
_, priority = self.task_info[taskId] # Get priority first
self.task_info.pop(taskId)
self.priority_queue.remove((-priority, -taskId))
4. Incorrect Extraction of TaskId in execTop()
Pitfall: Forgetting to negate the taskId when extracting it from the sorted list tuple.
Incorrect Implementation:
def execTop(self) -> int:
if not self.priority_queue:
return -1
task_id = self.priority_queue.pop(0)[1] # Wrong! This is negative
# task_id is actually -taskId, will cause KeyError in dictionary lookup
userId, _ = self.task_info[task_id] # KeyError!
Solution: Remember to negate the taskId to get the original value:
task_id = -self.priority_queue.pop(0)[1] # Correct: negate to get positive taskId
5. Not Checking for Empty Queue in execTop()
Pitfall: Attempting to pop from an empty sorted list will raise an IndexError
.
Incorrect Implementation:
def execTop(self) -> int:
# Dangerous: No check for empty queue
task_id = -self.priority_queue.pop(0)[1] # IndexError if empty!
# ...
Solution: Always check if the queue is empty before attempting to pop:
def execTop(self) -> int:
if not self.priority_queue: # Check for empty queue
return -1
task_id = -self.priority_queue.pop(0)[1]
# ...
Which data structure is used to implement priority queue?
Recommended Readings
https assets algo monster cover_photos heap svg Priority Queue and Heap What is the relationship between priority queue and heap Priority Queue is an Abstract Data Type and Heap is the concrete data structure we use to implement a priority queue Priority Queue A priority queue is a data structure
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!