1606. 找到处理最多请求的服务器
Difficulty
Hard
Tags
优先队列
Star
你有
k
个服务器,编号为 0
到 k-1
,它们可以同时处理多个请求组。每个服务器有无穷的计算能力但是 不能同时处理超过一个请求 。请求分配到服务器的规则如下:- 第
i
(序号从 0 开始)个请求到达。
- 如果所有服务器都已被占据,那么该请求被舍弃(完全不处理)。
- 如果第
(i % k)
个服务器空闲,那么对应服务器会处理该请求。
- 否则,将请求安排给下一个空闲的服务器(服务器构成一个环,必要的话可能从第 0 个服务器开始继续找下一个空闲的服务器)。比方说,如果第
i
个服务器在忙,那么会查看第(i+1)
个服务器,第(i+2)
个服务器等等。
给你一个 严格递增 的正整数数组
arrival
,表示第 i
个任务的到达时间,和另一个数组 load
,其中 load[i]
表示第 i
个请求的工作量(也就是服务器完成它所需要的时间)。你的任务是找到 最繁忙的服务器 。最繁忙定义为一个服务器处理的请求数是所有服务器里最多的。请你返回包含所有 最繁忙服务器 序号的列表,你可以以任意顺序返回这个列表。
示例 1:

输入:k = 3, arrival = [1,2,3,4,5], load = [5,2,3,3,3] 输出:[1] 解释: 所有服务器一开始都是空闲的。 前 3 个请求分别由前 3 台服务器依次处理。 请求 3 进来的时候,服务器 0 被占据,所以它被安排到下一台空闲的服务器,也就是服务器 1 。 请求 4 进来的时候,由于所有服务器都被占据,该请求被舍弃。 服务器 0 和 2 分别都处理了一个请求,服务器 1 处理了两个请求。所以服务器 1 是最忙的服务器。
示例 2:
输入:k = 3, arrival = [1,2,3,4], load = [1,2,1,2] 输出:[0] 解释: 前 3 个请求分别被前 3 个服务器处理。 请求 3 进来,由于服务器 0 空闲,它被服务器 0 处理。 服务器 0 处理了两个请求,服务器 1 和 2 分别处理了一个请求。所以服务器 0 是最忙的服务器。
示例 3:
输入:k = 3, arrival = [1,2,3], load = [10,12,11] 输出:[0,1,2] 解释:每个服务器分别处理了一个请求,所以它们都是最忙的服务器。
示例 4:
输入:k = 3, arrival = [1,2,3,4,8,9,10], load = [5,2,10,3,1,2,2] 输出:[1]
示例 5:
输入:k = 1, arrival = [1], load = [1] 输出:[0]
提示:
1 <= k <= 10
5
1 <= arrival.length, load.length <= 10
5
arrival.length == load.length
1 <= arrival[i], load[i] <= 10
9
arrival
保证 严格递增 。
法 1 优先队列
思路
题目要统计处理任务数最多的机器,首先容易想到使用「哈希表」统计每个机台处理的任务数,利用机台数量 k 最多不超过 ,我们可以开一个静态数组 来充当哈希表,同时维护一个当前处理的最大任务数量,最终所有满足 的机台集合即是答案。
再根据「每个任务有对应的开始时间和持续时间」以及「任务分配规则」,容易想到使用优先队列(堆)和有序集合(红黑树)来进行维护。
具体的,利用「每个任务有对应的开始时间和持续时间」,我们使用优先队列(堆)维护二元组 (idx, endTime)(idx,endTime),其中 idxidx 为机器编号,endTimeendTime 为当前机台所处理任务的结束时间(也就是该机台最早能够接受新任务的时刻),对于每个 arrival[i]arrival[i] 而言(新任务),我们先从优先队列中取出所有 endTime \leqslant arrival[i]endTime⩽arrival[i] 的机台 idxidx,加入「空闲池」,然后再按照「任务分配规则」从空闲池子中取机台,若取不到,则丢弃该任务。
由于「任务分配规则」是优先取大于等于 i % k 的最小值,若取不到,再取大于等于 00 的最小值。因此我们的「空闲池」最好是支持「二分」的有序集合,容易想到基于「红黑树」的 TreeSet 结构。
题解
import heapq from sortedcontainers import SortedList class Solution: def busiestServers(self, k: int, arrival: List[int], load: List[int]) -> List[int]: cnts = [0 for _ in range(k)] n, max_cnt = len(arrival), 0 busy, free = [], SortedList() for i in range(k): free.add(i) for i in range(n): start, end = arrival[i], arrival[i] + load[i] while busy and busy[0][0] <= start: free.add(busy[0][1]) heapq.heappop(busy) # 当前没有空余的服务器,跳过当前任务 if len(free) == 0: continue # 找大于等于 i%k 的最小值小标 idx = free.bisect_left(i % k) if idx == len(free): idx = 0 cur_id = free[idx] free.remove(cur_id) cnts[cur_id] += 1 heapq.heappush(busy, (end, cur_id)) max_cnt = max(max_cnt, cnts[cur_id]) return [i for i, cnt in enumerate(cnts) if cnt == max_cnt]