skip to content
Liu Yang's Blog

Leetcode#1822-使用服务器处理任务

/ 4 min read

Table of Contents

读题

这种模拟题读题是最麻烦的,题目是按tasks的顺序给servers分配任务,给servers分配任务时,选择最小weight且空闲的servers

需要注意的是,任务解锁的时候才能分配给服务器,当t=0时,第0件任务解锁,当t=1时,第1件任务解锁。

答案是,每个tasks分配给那个服务器。

思路

看一眼标签知道是用优先队列,不过按题目,每次取最小Weight, 其实就能想到小根堆/优先队列了,即当前可用服务器用优先队列表示。 若Weight有一样的,索引最小,那么我们也要把索引给作为比较条件。

这个其实就涉及到两个操作,一个是取服务器,一个是释放服务器。

拿Task的时候,可以将servers列表直接堆化,然后依次取就好,重要的是怎么表示服务器的占用和释放?

初步思路

初步的思路是,time是一个全局时间,我可以初始化一个数组,在取用哪个服务器的时候,将时间置为当前时间+任务时间,然后释放的时候,判断占用截至时间是否和当前时间一致,若是则直接扔到优先队列里。

优化版本

这样看似合理,但是释放的时候引入了循环,但是细想一下,释放的时候,不也是每次取最小的结束时间,然后和当前时间比?

所以表示占用的队列也可以变成优先队列,每次塞入(占用截至时间, idx)就好了。

特别考虑

如果服务器都在占用呢? 那么我可以直接当前time等于堆顶,即最小的占用截至时间,用来省略一些无意义的循环。

考虑任务解锁这个情况? time其实就相当于一个指针,指明了从0到time这个idx之间哪些任务是解锁的,所以一个时刻是可以放入多个任务的。

实现

代码写的有点丑,凑活看吧

import heapq
class Solution:
def assignTasks(self, servers: List[int], tasks: List[int]) -> List[int]:
pq, pq_busy, ans = [],[],[]
for k, v in enumerate(servers): heapq.heappush(pq, (v, k))
time, pt = 0,0
while pt < len(tasks):
# 放回server
Go = False
while not Go and len(pq_busy)!=0:
t, idx = pq_busy[0]
if t == time:
heapq.heappop(pq_busy)
heapq.heappush(pq, (servers[idx],idx))
else: Go = True
# 取server
while len(pq) !=0 and (time - pt + 1) >0 and pt < len(tasks):
weight, idx = heapq.heappop(pq)
heapq.heappush(pq_busy, (time + tasks[pt], idx))
ans.append(idx)
pt += 1
# 处理时间
time = time + 1 if len(pq_busy)!=len(servers) else pq_busy[0][0]
return ans