Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
You are given two 0-indexed integer arrays servers and tasks of lengths n and m respectively. servers[i] is the weight of the ith server, and tasks[j] is the time needed to process the jth task in seconds.
Tasks are assigned to the servers using a task queue. Initially, all servers are free, and the queue is empty.
At second j, the jth task is inserted into the queue (starting with the 0th task being inserted at second 0). As long as there are free servers and the queue is not empty, the task in the front of the queue will be assigned to a free server with the smallest weight, and in case of a tie, it is assigned to a free server with the smallest index.
If there are no free servers and the queue is not empty, we wait until a server becomes free and immediately assign the next task. If multiple servers become free at the same time, then multiple tasks from the queue will be assigned in order of insertion following the weight and index priorities above.
A server that is assigned task j at second t will be free again at second t + tasks[j].
Build an array ans of length m, where ans[j] is the index of the server the jth task will be assigned to.
Return the array ans.
Example 1:
Input: servers = [3,3,2], tasks = [1,2,3,2,1,2] Output: [2,2,0,2,1,2] Explanation: Events in chronological order go as follows: - At second 0, task 0 is added and processed using server 2 until second 1. - At second 1, server 2 becomes free. Task 1 is added and processed using server 2 until second 3. - At second 2, task 2 is added and processed using server 0 until second 5. - At second 3, server 2 becomes free. Task 3 is added and processed using server 2 until second 5. - At second 4, task 4 is added and processed using server 1 until second 5. - At second 5, all servers become free. Task 5 is added and processed using server 2 until second 7.
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] Explanation: Events in chronological order go as follows: - At second 0, task 0 is added and processed using server 1 until second 2. - At second 1, task 1 is added and processed using server 4 until second 2. - At second 2, servers 1 and 4 become free. Task 2 is added and processed using server 1 until second 4. - At second 3, task 3 is added and processed using server 4 until second 7. - At second 4, server 1 becomes free. Task 4 is added and processed using server 1 until second 9. - At second 5, task 5 is added and processed using server 3 until second 7. - At second 6, task 6 is added and processed using server 2 until second 7.
Constraints:
servers.length == ntasks.length == m1 <= n, m <= 2 * 1051 <= servers[i], tasks[j] <= 2 * 105Problem summary: You are given two 0-indexed integer arrays servers and tasks of lengths n and m respectively. servers[i] is the weight of the ith server, and tasks[j] is the time needed to process the jth task in seconds. Tasks are assigned to the servers using a task queue. Initially, all servers are free, and the queue is empty. At second j, the jth task is inserted into the queue (starting with the 0th task being inserted at second 0). As long as there are free servers and the queue is not empty, the task in the front of the queue will be assigned to a free server with the smallest weight, and in case of a tie, it is assigned to a free server with the smallest index. If there are no free servers and the queue is not empty, we wait until a server becomes free and immediately assign the next task. If multiple servers become free at the same time, then multiple tasks
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array
[3,3,2] [1,2,3,2,1,2]
[5,1,4,3,2] [2,1,2,4,5,2,1]
parallel-courses-iii)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1882: Process Tasks Using Servers
class Solution {
public int[] assignTasks(int[] servers, int[] tasks) {
int n = servers.length;
PriorityQueue<int[]> idle = new PriorityQueue<>((a, b) -> {
if (a[0] != b[0]) {
return a[0] - b[0];
}
return a[1] - b[1];
});
PriorityQueue<int[]> busy = new PriorityQueue<>((a, b) -> {
if (a[0] != b[0]) {
return a[0] - b[0];
}
if (a[1] != b[1]) {
return a[1] - b[1];
}
return a[2] - b[2];
});
for (int i = 0; i < n; i++) {
idle.offer(new int[] {servers[i], i});
}
int m = tasks.length;
int[] ans = new int[m];
for (int j = 0; j < m; ++j) {
int t = tasks[j];
while (!busy.isEmpty() && busy.peek()[0] <= j) {
int[] p = busy.poll();
idle.offer(new int[] {p[1], p[2]});
}
if (!idle.isEmpty()) {
int i = idle.poll()[1];
ans[j] = i;
busy.offer(new int[] {j + t, servers[i], i});
} else {
int[] p = busy.poll();
int i = p[2];
ans[j] = i;
busy.offer(new int[] {p[0] + t, p[1], i});
}
}
return ans;
}
}
// Accepted solution for LeetCode #1882: Process Tasks Using Servers
func assignTasks(servers []int, tasks []int) (ans []int) {
idle := hp{}
busy := hp2{}
for i, x := range servers {
heap.Push(&idle, pair{x, i})
}
for j, t := range tasks {
for len(busy) > 0 && busy[0].w <= j {
p := heap.Pop(&busy).(tuple)
heap.Push(&idle, pair{p.s, p.i})
}
if idle.Len() > 0 {
p := heap.Pop(&idle).(pair)
ans = append(ans, p.i)
heap.Push(&busy, tuple{j + t, p.s, p.i})
} else {
p := heap.Pop(&busy).(tuple)
ans = append(ans, p.i)
heap.Push(&busy, tuple{p.w + t, p.s, p.i})
}
}
return
}
type pair struct {
s int
i int
}
type hp []pair
func (h hp) Len() int { return len(h) }
func (h hp) Less(i, j int) bool {
a, b := h[i], h[j]
return a.s < b.s || a.s == b.s && a.i < b.i
}
func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *hp) Push(v any) { *h = append(*h, v.(pair)) }
func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
type tuple struct {
w int
s int
i int
}
type hp2 []tuple
func (h hp2) Len() int { return len(h) }
func (h hp2) Less(i, j int) bool {
a, b := h[i], h[j]
return a.w < b.w || a.w == b.w && (a.s < b.s || a.s == b.s && a.i < b.i)
}
func (h hp2) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *hp2) Push(v any) { *h = append(*h, v.(tuple)) }
func (h *hp2) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
# Accepted solution for LeetCode #1882: Process Tasks Using Servers
class Solution:
def assignTasks(self, servers: List[int], tasks: List[int]) -> List[int]:
idle = [(x, i) for i, x in enumerate(servers)]
heapify(idle)
busy = []
ans = []
for j, t in enumerate(tasks):
while busy and busy[0][0] <= j:
_, s, i = heappop(busy)
heappush(idle, (s, i))
if idle:
s, i = heappop(idle)
heappush(busy, (j + t, s, i))
else:
w, s, i = heappop(busy)
heappush(busy, (w + t, s, i))
ans.append(i)
return ans
// Accepted solution for LeetCode #1882: Process Tasks Using Servers
/**
* [1882] Process Tasks Using Servers
*
* You are given two 0-indexed integer arrays servers and tasks of lengths n and m respectively. servers[i] is the weight of the i^th server, and tasks[j] is the time needed to process the j^th task in seconds.
* Tasks are assigned to the servers using a task queue. Initially, all servers are free, and the queue is empty.
* At second j, the j^th task is inserted into the queue (starting with the 0^th task being inserted at second 0). As long as there are free servers and the queue is not empty, the task in the front of the queue will be assigned to a free server with the smallest weight, and in case of a tie, it is assigned to a free server with the smallest index.
* If there are no free servers and the queue is not empty, we wait until a server becomes free and immediately assign the next task. If multiple servers become free at the same time, then multiple tasks from the queue will be assigned in order of insertion following the weight and index priorities above.
* A server that is assigned task j at second t will be free again at second t + tasks[j].
* Build an array ans of length m, where ans[j] is the index of the server the j^th task will be assigned to.
* Return the array ans.
*
* Example 1:
*
* Input: servers = [3,3,2], tasks = [1,2,3,2,1,2]
* Output: [2,2,0,2,1,2]
* Explanation: Events in chronological order go as follows:
* - At second 0, task 0 is added and processed using server 2 until second 1.
* - At second 1, server 2 becomes free. Task 1 is added and processed using server 2 until second 3.
* - At second 2, task 2 is added and processed using server 0 until second 5.
* - At second 3, server 2 becomes free. Task 3 is added and processed using server 2 until second 5.
* - At second 4, task 4 is added and processed using server 1 until second 5.
* - At second 5, all servers become free. Task 5 is added and processed using server 2 until second 7.
* 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]
* Explanation: Events in chronological order go as follows:
* - At second 0, task 0 is added and processed using server 1 until second 2.
* - At second 1, task 1 is added and processed using server 4 until second 2.
* - At second 2, servers 1 and 4 become free. Task 2 is added and processed using server 1 until second 4.
* - At second 3, task 3 is added and processed using server 4 until second 7.
* - At second 4, server 1 becomes free. Task 4 is added and processed using server 1 until second 9.
* - At second 5, task 5 is added and processed using server 3 until second 7.
* - At second 6, task 6 is added and processed using server 2 until second 7.
*
*
* Constraints:
*
* servers.length == n
* tasks.length == m
* 1 <= n, m <= 2 * 10^5
* 1 <= servers[i], tasks[j] <= 2 * 10^5
*
*/
pub struct Solution {}
// problem: https://leetcode.com/problems/process-tasks-using-servers/
// discuss: https://leetcode.com/problems/process-tasks-using-servers/discuss/?currentPage=1&orderBy=most_votes&query=
// submission codes start here
impl Solution {
pub fn assign_tasks(servers: Vec<i32>, tasks: Vec<i32>) -> Vec<i32> {
vec![]
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn test_1882_example_1() {
let servers = vec![3, 3, 2];
let tasks = vec![1, 2, 3, 2, 1, 2];
let result = vec![2, 2, 0, 2, 1, 2];
assert_eq!(Solution::assign_tasks(servers, tasks), result);
}
#[test]
#[ignore]
fn test_1882_example_2() {
let servers = vec![5, 1, 4, 3, 2];
let tasks = vec![2, 1, 2, 4, 5, 2, 1];
let result = vec![1, 4, 1, 4, 1, 3, 2];
assert_eq!(Solution::assign_tasks(servers, tasks), result);
}
}
// Accepted solution for LeetCode #1882: Process Tasks Using Servers
function assignTasks(servers: number[], tasks: number[]): number[] {
const idle = new PriorityQueue({
compare: (a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]),
});
const busy = new PriorityQueue({
compare: (a, b) =>
a[0] === b[0] ? (a[1] === b[1] ? a[2] - b[2] : a[1] - b[1]) : a[0] - b[0],
});
for (let i = 0; i < servers.length; ++i) {
idle.enqueue([servers[i], i]);
}
const ans: number[] = [];
for (let j = 0; j < tasks.length; ++j) {
const t = tasks[j];
while (busy.size() > 0 && busy.front()![0] <= j) {
const [_, s, i] = busy.dequeue()!;
idle.enqueue([s, i]);
}
if (idle.size() > 0) {
const [s, i] = idle.dequeue()!;
busy.enqueue([j + t, s, i]);
ans.push(i);
} else {
const [w, s, i] = busy.dequeue()!;
busy.enqueue([w + t, s, i]);
ans.push(i);
}
}
return ans;
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.