05 August 2008
给你两个 下标从 0 开始 的整数数组 servers 和 tasks ,长度分别为 n 和 m 。servers[i] 是第 i 台服务器的 权重 ,而 tasks[j] 是处理第 j 项任务 所需要的时间(单位:秒)。
你正在运行一个仿真系统,在处理完所有任务后,该系统将会关闭。每台服务器只能同时处理一项任务。第 0 项任务在第 0 秒可以开始处理,相应地,第 j 项任务在第 j 秒可以开始处理。处理第 j 项任务时,你需要为它分配一台 权重最小 的空闲服务器。如果存在多台相同权重的空闲服务器,请选择 下标最小 的服务器。如果一台空闲服务器在第 t 秒分配到第 j 项任务,那么在 t + tasks[j] 时它将恢复空闲状态。
如果没有空闲服务器,则必须等待,直到出现一台空闲服务器,并 尽可能早 地处理剩余任务。 如果有多项任务等待分配,则按照 下标递增 的顺序完成分配。
如果同一时刻存在多台空闲服务器,可以同时将多项任务分别分配给它们。
构建长度为 m 的答案数组 ans ,其中 ans[j] 是第 j 项任务分配的服务器的下标。
返回答案数组 ans 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
class Solution {
public int[] assignTasks(int[] servers, int[] tasks) {
//定义优先队列sq1(存入long[]{服务器标号 , 权重}),并重写Comparator(权重从小到大,标号从小到大)
PriorityQueue<long[]> pq1 = new PriorityQueue<long[]>((a, b) -> {
if (a[1] == b[1]) {
return (int) (a[0] - b[0]);
}
return (int) (a[1] - b[1]);
});
//定义优先队列sq2(存入long[]{服务器标号 , 权重 , 服务器完成工作时间}),并重写Comparator(完成工作时间从小到大)
PriorityQueue<long[]> pq2 = new PriorityQueue<long[]>(new Comparator<long[]>() {
public int compare(long[] a, long[] b) {
return (int) (a[2] - b[2]);
}
});
for (int i = 0; i < servers.length; i++) {
pq1.offer(new long[]{i, servers[i]});
}
int len = tasks.length;
int[] result = new int[len];
int r = 0;
Deque<Integer> lst = new LinkedList<>();
for (int i = 0; i < len; i++) {
//检测sq2中是否有 完成时间小于<=当前时间的服务器,若有,则从sq2中取出该服务器并加入sq1中
while (!pq2.isEmpty() && pq2.peek()[2] <= i) {
long[] tas = pq2.poll();
pq1.offer(new long[]{tas[0], tas[1]});
}
//任务从尾部进入队列
lst.offerLast(tasks[i]);
//当sq1和lst都不为空时,说明有任务可以加到服务器中,此时从lst头部取出任务,并从sq1中取出服务器,两者结合后添加到sq2中
//题目原话:如果同一时刻存在多台空闲服务器,可以同时将多项任务分别分配给它们。(很重要)
while (!pq1.isEmpty() && !lst.isEmpty()) {
long[] ser = pq1.poll();
result[r++] = (int) ser[0];
pq2.offer(new long[]{ser[0], ser[1], i + lst.pollFirst()});
}
}
long t = len;
//若是lst依旧不为空,说明服务器资源已满,需要等待
while (!lst.isEmpty()) {
//因此我们取出完成时间最小的所有服务器(多个服务器可能会同时解放)
if (!pq2.isEmpty()) {
//需把时间t置为服务器解放时间(很多超时是因为t逐一累加)
t = pq2.peek()[2];
while (!pq2.isEmpty() && pq2.peek()[2] == t) {
long[] tas = pq2.poll();
pq1.offer(new long[]{tas[0], tas[1]});
}
}
//仿照上面把任务添加进空闲服务器
while (!pq1.isEmpty() && !lst.isEmpty()) {
long[] ser = pq1.poll();
result[r++] = (int) ser[0];
pq2.offer(new long[]{ser[0], ser[1], t + lst.pollFirst()});
}
}
return result;
}
}