Process Tasks Using Servers — Medium Problem & Solution

servers[i] is the weight of server i, and tasks[j] is how many seconds task j needs. Task j is queued at second j.

  • Difficulty: Medium
  • Topics: Arrays, Simulation, Heap
  • Asked at: Amazon, Google, Microsoft
  • Time limit: 2 s
  • Memory limit: 256 MB
  • Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby

Problem statement

servers[i] is the weight of server i, and tasks[j] is how many seconds task j needs. Task j is queued at second j.

At each second, as long as the queue is non-empty and a server is free, the front task is assigned to the free server with the smallest weight, breaking ties by the smallest index. If every server is busy, the queue waits until one frees up, and then the waiting tasks are assigned in order. Return the server index each task is assigned to.

Example 1

Input: servers = [3,3,2], tasks = [1,2,3,2,1,2]
Output: [2,2,0,2,1,2]

Example 2

Input: servers = [5,1,4,3,2], tasks = [2,1,2,4,5,2,1]
Output: [1,4,1,4,1,3,2]

Example 3

Input: servers = [1], tasks = [5,5]
Output: [0,0]
Explanation: One server runs both, the second after the first finishes.

Constraints

  • servers.length == n
  • tasks.length == m
  • 1 <= n, m <= 2000
  • 1 <= servers[i], tasks[j] <= 2 * 10^5

How to solve Process Tasks Using Servers

Simulate with two priority queues — free servers keyed on (weight, index) and busy servers keyed on finish time. Task j starts at second j if anything is free, and otherwise at the moment the first server frees up.

Approach

  1. Before task j, return every server whose finish time is at most the current second to the free pool.
  2. If the free pool is empty, advance the clock to the earliest finish and return those servers.
  3. Assign the task to the smallest (weight, index) free server and record it.
  4. Move that server to the busy pool with finish time start + tasks[j].

Why it works

The queue never needs to be modelled explicitly: because tasks arrive one per second and are served strictly in order, handling task j in a loop already gives FIFO. Jumping the clock rather than ticking is what keeps the simulation linear in the task count instead of the time range.

Complexity

  • Time — O((n + m) log n)
  • Space — O(n + m)

Pitfalls

  • Ties on weight go to the smaller server index, not to whichever was freed first.
  • A task that waits starts when the server frees, not at second j.
  • Servers freed at exactly the current second are available.

Reference solution

Python

from typing import List
import heapq

def assignTasks(servers: List[int], tasks: List[int]) -> List[int]:
    free = [(w, i) for i, w in enumerate(servers)]
    heapq.heapify(free)
    busy = []
    out = []
    for j, need in enumerate(tasks):
        while busy and busy[0][0] <= j:
            _, w, i = heapq.heappop(busy)
            heapq.heappush(free, (w, i))
        if not free:
            start = busy[0][0]
            while busy and busy[0][0] <= start:
                _, w, i = heapq.heappop(busy)
                heapq.heappush(free, (w, i))
        else:
            start = j
        w, i = heapq.heappop(free)
        out.append(i)
        heapq.heappush(busy, (start + need, w, i))
    return out

JavaScript

var assignTasks = function(servers, tasks) {
    var m = servers.length, i, t;
    var freeAt = [];
    for (i = 0; i < m; i++) freeAt.push(0);
    var out = [];
    for (var j = 0; j < tasks.length; j++) {
        var avail = [];
        for (i = 0; i < m; i++) if (freeAt[i] <= j) avail.push(i);
        var start = j;
        if (avail.length === 0) {
            start = freeAt[0];
            for (i = 1; i < m; i++) if (freeAt[i] < start) start = freeAt[i];
            for (i = 0; i < m; i++) if (freeAt[i] <= start) avail.push(i);
        }
        var pick = avail[0];
        for (t = 1; t < avail.length; t++) {
            var s = avail[t];
            if (servers[s] < servers[pick] || (servers[s] === servers[pick] && s < pick)) pick = s;
        }
        out.push(pick);
        freeAt[pick] = start + tasks[j];
    }
    return out;
};

Also on the editorial tab: C, C#, C++, Go, Java, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.

All 667 arrays problems · the whole catalogue