Process Tasks Using Servers

Sanjeev SharmaSanjeev Sharma
3 min read

Advertisement

Problem

Assign tasks[i] (weight) to free server with min weight (tie: min index) at time i or earliest possible.

Key insight (Two Heaps):

  • free: min-heap by (weight, index) — available servers
  • busy: min-heap by (free_at, weight, index) — working servers

Solutions

// C++
vector<int> assignTasks(vector<int>& servers, vector<int>& tasks) {
    using T3 = tuple<int,int,int>;
    priority_queue<T3, vector<T3>, greater<T3>> free, busy;
    for (int i = 0; i < (int)servers.size(); i++) free.push({servers[i], i, 0});
    int t = 0;
    vector<int> res;
    for (int i = 0; i < (int)tasks.size(); i++) {
        t = max(t, i);
        // release servers that finished
        while (!busy.empty() && get<0>(busy.top()) <= t) {
            auto [ft, w, idx] = busy.top(); busy.pop();
            free.push({w, idx, 0});
        }
        if (free.empty()) {
            // jump to next server free time
            auto [ft, w, idx] = busy.top(); busy.pop();
            t = ft;
            free.push({w, idx, 0});
            while (!busy.empty() && get<0>(busy.top()) == t) {
                auto [ft2, w2, idx2] = busy.top(); busy.pop();
                free.push({w2, idx2, 0});
            }
        }
        auto [w, idx, _] = free.top(); free.pop();
        res.push_back(idx);
        busy.push({t + tasks[i], w, idx});
    }
    return res;
}
// Java
public int[] assignTasks(int[] servers, int[] tasks) {
    PriorityQueue<int[]> free = new PriorityQueue<>((a,b)->a[0]!=b[0]?a[0]-b[0]:a[1]-b[1]);
    PriorityQueue<int[]> busy = new PriorityQueue<>((a,b)->a[0]!=b[0]?a[0]-b[0]:a[1]!=b[1]?a[1]-b[1]:a[2]-b[2]);
    for (int i = 0; i < servers.length; i++) free.offer(new int[]{servers[i], i});
    int t = 0;
    int[] res = new int[tasks.length];
    for (int i = 0; i < tasks.length; i++) {
        t = Math.max(t, i);
        while (!busy.isEmpty() && busy.peek()[0] <= t) {
            int[] s = busy.poll(); free.offer(new int[]{s[1], s[2]});
        }
        if (free.isEmpty()) {
            int[] s = busy.poll(); t = s[0]; free.offer(new int[]{s[1], s[2]});
            while (!busy.isEmpty() && busy.peek()[0] == t) { s = busy.poll(); free.offer(new int[]{s[1], s[2]}); }
        }
        int[] s = free.poll(); res[i] = s[1];
        busy.offer(new int[]{t + tasks[i], s[0], s[1]});
    }
    return res;
}
# Python
import heapq

def assignTasks(servers, tasks):
    free = [(w, i) for i, w in enumerate(servers)]
    heapq.heapify(free)
    busy = []  # (free_at, weight, idx)
    result = []
    t = 0
    for i, task in enumerate(tasks):
        t = max(t, i)
        while busy and busy[0][0] <= t:
            ft, w, idx = heapq.heappop(busy)
            heapq.heappush(free, (w, idx))
        if not free:
            ft, w, idx = heapq.heappop(busy)
            t = ft
            heapq.heappush(free, (w, idx))
            while busy and busy[0][0] == t:
                ft2, w2, idx2 = heapq.heappop(busy)
                heapq.heappush(free, (w2, idx2))
        w, idx = heapq.heappop(free)
        result.append(idx)
        heapq.heappush(busy, (t + task, w, idx))
    return result
// JavaScript (simplified with sorting)
function assignTasks(servers, tasks) {
    // See Python/C++ for heap-based solution
    // Simplified O(n*m) solution:
    const free = servers.map((w, i) => ({w, i, freeAt: 0}));
    const result = [];
    for (let i = 0; i < tasks.length; i++) {
        const t = i;
        let best = null;
        for (const s of free) {
            if (s.freeAt <= t) {
                if (!best || s.w < best.w || (s.w === best.w && s.i < best.i)) best = s;
            }
        }
        if (!best) {
            const earliest = Math.min(...free.map(s => s.freeAt));
            for (const s of free) if (s.freeAt === earliest) {
                if (!best || s.w < best.w || (s.w === best.w && s.i < best.i)) best = s;
            }
        }
        result.push(best.i);
        best.freeAt = Math.max(best.freeAt, t) + tasks[i];
    }
    return result;
}

Complexity

  • Time: O((n+m) log n) where n=servers, m=tasks
  • Space: O(n)

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro