Build a Removable Timestamp-Ordered Task Scheduler
Company: Bytedance
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
## Problem
Implement a task scheduler with three operations:
```text
addTask(taskId, timestamp)
removeTask(taskId)
popTasks(count)
```
`addTask` inserts one task. `removeTask` removes that task if it is currently scheduled. `popTasks(count)` removes and returns up to `count` scheduled task IDs in ascending order of start timestamp. When timestamps tie, smaller task IDs come first.
Process a sequence of operations and return one array for every `pop` operation.
### Function Contract
Implement `runTaskScheduler(operations)`, where an operation is:
```text
["add", taskId, timestamp]
["remove", taskId]
["pop", count]
```
Return an array of task-ID arrays, one per `pop`, in operation order.
### Constraints & Assumptions
- `0 <= len(operations) <= 200,000`.
- `taskId` and `timestamp` are signed 64-bit integers.
- An `add` uses a task ID that is not currently scheduled. A previously removed or popped ID may be added again.
- Removing an absent task is a no-op.
- `count >= 0`; if fewer than `count` tasks remain, return and remove all of them.
- A `pop` with `count = 0` returns an empty array and changes no state.
### Clarifying Questions to Ask
- Does `pop` only inspect tasks or remove them? It removes every returned task.
- How are equal timestamps ordered? By increasing task ID.
- May removed task IDs be reused? Yes.
- What happens when `remove` names an absent task? Nothing.
```hint Combine ordering with membership
A min-heap gives the next timestamp, while a map or set records which task version is still active.
```
```hint Make reused IDs safe
If removal is lazy, attach a generation number to each heap entry so an old entry cannot remove a later task that reused the same ID.
```
### Example
```text
operations = [
["add", 7, 30],
["add", 2, 10],
["add", 5, 10],
["remove", 2],
["pop", 2],
["pop", 1]
]
```
Return `[[5, 7], []]`.
### Evaluation Focus
- Removes tasks returned by `pop` and never returns a removed task.
- Applies the timestamp-and-ID ordering deterministically.
- Handles stale heap entries and reuse of a task ID correctly.
- Runs each add or remove in `O(log n)` or better and returns `m` popped tasks in `O(m log n)` or better.
### Extensions to Discuss
1. How would an operation that changes a scheduled timestamp be supported?
2. What cleanup policy bounds stale heap entries after many removals?
3. How would the scheduler block until the earliest wall-clock timestamp becomes due?
Quick Answer: Build a task scheduler that supports insertion, removal, and bounded popping in timestamp order, using smaller task IDs to break equal-timestamp ties.
addTask inserts one task. removeTask removes that task if it is currently scheduled. popTasks(count) removes and returns up to count scheduled task IDs in ascending order of start timestamp. When timestamps tie, smaller task IDs come first.
Process a sequence of operations and return one array for every pop operation.
Function Contract
Implement runTaskScheduler(operations), where an operation is: