diff --git "a/LeetCode/1601-1610/1606. \346\211\276\345\210\260\345\244\204\347\220\206\346\234\200\345\244\232\350\257\267\346\261\202\347\232\204\346\234\215\345\212\241\345\231\250\357\274\210\345\233\260\351\232\276\357\274\211.md" "b/LeetCode/1601-1610/1606. \346\211\276\345\210\260\345\244\204\347\220\206\346\234\200\345\244\232\350\257\267\346\261\202\347\232\204\346\234\215\345\212\241\345\231\250\357\274\210\345\233\260\351\232\276\357\274\211.md" index 35cf024d..a6874903 100644 --- "a/LeetCode/1601-1610/1606. \346\211\276\345\210\260\345\244\204\347\220\206\346\234\200\345\244\232\350\257\267\346\261\202\347\232\204\346\234\215\345\212\241\345\231\250\357\274\210\345\233\260\351\232\276\357\274\211.md" +++ "b/LeetCode/1601-1610/1606. \346\211\276\345\210\260\345\244\204\347\220\206\346\234\200\345\244\232\350\257\267\346\261\202\347\232\204\346\234\215\345\212\241\345\231\250\357\274\210\345\233\260\351\232\276\357\274\211.md" @@ -81,7 +81,7 @@ Tag : 「数据结构」、「优先队列」、「堆」、「红黑树」、 再根据「每个任务有对应的开始时间和持续时间」以及「任务分配规则」,容易想到使用优先队列(堆)和有序集合(红黑树)来进行维护。 -具体的,利用「每个任务有对应的开始时间和持续时间」,我们使用优先队列(堆)维护二元组 $(idx, endTime)$,其中 $idx$ 为机器编号,$endTime$ 为当前机台所处理任务的结束时间(也就是该机台最早能够接受新任务的时刻),对于每个 $arrival[i]$ 而言(新任务),我们先从优先队列中取出所有 $endTime < arrival[i]$ 的机台 $idx$,加入「空闲池」,然后再按照「任务分配规则」从空闲池子中取机台,若取不到,则丢弃该任务。 +具体的,利用「每个任务有对应的开始时间和持续时间」,我们使用优先队列(堆)维护二元组 $(idx, endTime)$,其中 $idx$ 为机器编号,$endTime$ 为当前机台所处理任务的结束时间(也就是该机台最早能够接受新任务的时刻),对于每个 $arrival[i]$ 而言(新任务),我们先从优先队列中取出所有 $endTime \leqslant arrival[i]$ 的机台 $idx$,加入「空闲池」,然后再按照「任务分配规则」从空闲池子中取机台,若取不到,则丢弃该任务。 由于「任务分配规则」是优先取大于等于 `i % k` 的最小值,若取不到,再取大于等于 $0$ 的最小值。因此我们的「空闲池」最好是支持「二分」的有序集合,容易想到基于「红黑树」的 `TreeSet` 结构。 @@ -114,6 +114,29 @@ class Solution { } } ``` + +```Python +from sortedcontainers import SortedList + +class Solution: + def busiestServers(self, k: int, arrival: List[int], load: List[int]) -> List[int]: + cnts = [0] * k + n, m = len(arrival), 0 + busy, free = [], SortedList(range(k)) + 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]) + heappop(busy) + if (idx := free.bisect_left(i % k)) == len(free) == (idx := free.bisect_left(0)): + continue + u = free[idx] + free.remove(u) + heappush(busy, (end, u)) + cnts[u] += 1 + m = max(m, cnts[u]) + return [i for i in range(k) if cnts[i] == m] +``` * 时间复杂度:令任务数量为 $n$,机台数量为 $k$,起始将所有机台存入 `TreeSet`,复杂度为 $O(k\log{k})$;每次处理新的 $arrival[i]$ 时,先从优先队列取出可接受新任务的机台,存入 `TreeSet`,然后从 `TreeSet` 中取出最多一个的机台来完成任务,其中从 `TreeSet` 中取出机台最多调用两次的 `ceiling` 操作,复杂度为 $O(\log{k})$,这部分的整体复杂度为 $O(n\log{k})$;统计处理任务数达到 `max` 的机台集合复杂度为 $O(k)$;整体复杂度为 $O((k + n)\log{k})$ * 空间复杂度:$O(k)$