3408. Design Task Manager
题目简介
题目要求我们实现一个 TaskManager
系统用于管理任务,并实现以下方法:
add(int userId, int taskId, int priority)
edit(int taskId, int newPriority)
rmv(int taskId)
execTop()
解题思路
这题也是在考我们关于大顶堆的实现
- 在构造函数的时候,我们需要用 map 来建立 task 跟 user 以及 priority 的映射,以及构建好大顶堆
- 在实现
add
方法的时候我们只需要将新的映射 add 进 map 中,并且 push 到大顶堆中就好 edit
与 add 相似,只是需要从 map 中将原来的映射覆盖,大顶堆中的数据则先搁置不需要删除rmv
也是一样的,区别在于要将原来 map 中的 task 删除execTop
时,我们需要对比当前大顶堆堆顶的数据是否还在 map 中,如果不是需要重新获取堆顶直到获取到了与 map 数据符合的 task,此时我们返回 userId 并将当前 task 使用rmv
删除就好
Javascript(自己构建 maxHeap)
/**
* @param {number[][]} tasks
*/
var TaskManager = function (tasks) {
this.taskToUserId = new Map()
this.taskToPriority = new Map()
this.maxHeap = new MyMaxHeap()
for (const [userId, taskId, priority] of tasks) {
this.taskToUserId.set(taskId, userId)
this.taskToPriority.set(taskId, priority)
this.maxHeap.push([taskId, priority])
}
};
/**
* @param {number} userId
* @param {number} taskId
* @param {number} priority
* @return {void}
*/
TaskManager.prototype.add = function (userId, taskId, priority) {
this.taskToUserId.set(taskId, userId)
this.taskToPriority.set(taskId, priority)
this.maxHeap.push([taskId, priority])
};
/**
* @param {number} taskId
* @param {number} newPriority
* @return {void}
*/
TaskManager.prototype.edit = function (taskId, newPriority) {
this.taskToPriority.set(taskId, newPriority)
this.maxHeap.push([taskId, newPriority])
};
/**
* @param {number} taskId
* @return {void}
*/
TaskManager.prototype.rmv = function (taskId) {
this.taskToPriority.delete(taskId)
this.taskToUserId.delete(taskId)
};
/**
* @return {number}
*/
TaskManager.prototype.execTop = function () {
while (!this.maxHeap.isEmpty()) {
const [taskId, priority] = this.maxHeap.pop()
if (this.taskToPriority.has(taskId) && priority === this.taskToPriority.get(taskId)) {
const userId = this.taskToUserId.get(taskId)
this.rmv(taskId)
return userId
}
}
return -1
};
class MyMaxHeap {
constructor() {
this.heap = []
}
isEmpty() {
return this.heap.length === 0
}
peek() {
return this.heap[0]
}
push(item) {
this.heap.push(item)
this.heapifyUp(this.heap.length - 1)
}
pop() {
if (this.heap.length <= 1) {
return this.heap.pop()
}
const res = this.peek()
this.heap[0] = this.heap.pop()
this.heapifyDown(0)
return res
}
heapifyUp(index) {
const parent = Math.floor((index - 1) / 2)
if (parent >= 0 && this.compare(this.heap[parent], this.heap[index]) > 0) {
[this.heap[parent], this.heap[index]] = [this.heap[index], this.heap[parent]]
this.heapifyUp(parent)
}
}
heapifyDown(index) {
const left = index * 2 + 1
const right = index * 2 + 2
let max = index
if (left < this.heap.length && this.compare(this.heap[left], this.heap[max]) < 0) {
max = left
}
if (right < this.heap.length && this.compare(this.heap[right], this.heap[max]) < 0) {
max = right
}
if (max !== index) {
[this.heap[max], this.heap[index]] = [this.heap[index], this.heap[max]]
this.heapifyDown(max)
}
}
compare([taskA, priorityA], [taskB, priorityB]) {
if (priorityB === priorityA) {
return taskB - taskA
}
return priorityB - priorityA
}
}
Javascript(使用 PriorityQueue)
/**
* @param {number[][]} tasks
*/
var TaskManager = function(tasks) {
this.taskToUserId = new Map()
this.taskToPriority = new Map()
this.queue = new PriorityQueue(([taskA, priorityA], [taskB, priorityB]) => {
if(priorityA === priorityB) {
return taskB - taskA
}
return priorityB - priorityA
})
for(const [userId, taskId, priority] of tasks) {
this.taskToUserId.set(taskId, userId)
this.taskToPriority.set(taskId, priority)
this.queue.enqueue([taskId, priority])
}
};
/**
* @param {number} userId
* @param {number} taskId
* @param {number} priority
* @return {void}
*/
TaskManager.prototype.add = function(userId, taskId, priority) {
this.taskToUserId.set(taskId, userId)
this.taskToPriority.set(taskId, priority)
this.queue.enqueue([taskId, priority])
};
/**
* @param {number} taskId
* @param {number} newPriority
* @return {void}
*/
TaskManager.prototype.edit = function(taskId, newPriority) {
this.taskToPriority.set(taskId, newPriority)
this.queue.enqueue([taskId, newPriority])
};
/**
* @param {number} taskId
* @return {void}
*/
TaskManager.prototype.rmv = function(taskId) {
this.taskToPriority.delete(taskId)
this.taskToUserId.delete(taskId)
};
/**
* @return {number}
*/
TaskManager.prototype.execTop = function() {
while (!this.queue.isEmpty()) {
const [taskId, priority] = this.queue.dequeue()
if (this.taskToPriority.has(taskId) && priority === this.taskToPriority.get(taskId)) {
const userId = this.taskToUserId.get(taskId)
this.rmv(taskId)
return userId
}
}
return -1
};
/**
* Your TaskManager object will be instantiated and called as such:
* var obj = new TaskManager(tasks)
* obj.add(userId,taskId,priority)
* obj.edit(taskId,newPriority)
* obj.rmv(taskId)
* var param_4 = obj.execTop()
*/