Assign Tasks to the Minimum Number of Workers
LyftSoftware Engineer · OnsiteLast updated
Assign interval tasks to the minimum number of workers while preserving deterministic worker IDs and original output order. Reason about overlapping times, tie handling, resource reuse, efficient scheduling at scale, and boundary cases where one task ends as another begins.
Assign Tasks to the Minimum Number of Workers
Problem
Implement assignMinimumWorkers(tasks) -> workerIds.
Each task is [startMinute, durationMinutes]. startMinute is the task's start time measured from the beginning of one day, and durationMinutes is its elapsed processing time. A worker can process only one task at a time and becomes available at startMinute + durationMinutes.
Assign every task while using the minimum possible number of workers. When more than one existing worker is available for a task, choose the available worker with the smallest ID. Worker IDs start at 0 and each newly needed worker receives the next consecutive ID.
Process tasks by increasing start time; tasks with the same start time are processed by their original input index. Return the assigned worker ID for every task in original input order.
Portable Contract
tasksis a JSON array of two-integer arrays[startMinute, durationMinutes].0 <= tasks.length <= 12,000.0 <= startMinute < 1,440and1 <= durationMinutes <= 1,000,000.- A task may finish after midnight; times are elapsed minutes on one common timeline and do not wrap back to zero.
- Duplicate tasks and equal start times are allowed.
- A worker whose previous task ends at minute
tis available for a task starting at minutet. - Do not modify
tasks. - Let
Bbe the compact UTF-8 JSON byte length oftasks, counting every bracket, comma, and digit. Inputs satisfyB <= 96,000. - Let
Rbe the compact UTF-8 JSON byte length of the returned integer array. Inputs guaranteeR <= 72,000, so the serialized input plus result is at most168,000bytes. - Target
O(n log n)time andO(n)auxiliary space forn = tasks.length.
All four languages use homogeneous integer containers: list[list[int]] returning list[int] in Python, nested arrays returning an array in JavaScript, List<List<Integer>> returning List<Integer> in Java, and vector<vector<int>> returning vector<int> in C++.
Examples
tasks = [[60, 30], [70, 10], [90, 15], [60, 5]]
workerIds = [0, 1, 0, 1]
tasks = [[0, 10], [10, 5], [10, 7]]
workerIds = [0, 0, 1]
Discussion Requirements
- Explain why processing by start time and reusing every eligible worker minimizes the worker count.
- Identify the ordering keys for busy workers and available workers.
- Explain the original-index tie-break for equal start times and why the final result is reordered by input index.
- Test empty input, touching tasks, equal starts, simultaneous releases, duplicate tasks, and a case where several free workers are available.
Hints
Hint 1
Separate busy and reusable workers: The next worker to finish and the smallest worker ID that is already free are different orderings.
Hint 2
Release every eligible worker first: Before assigning a task, make all workers whose end time is no later than its start time available for the tie-break.
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.