|
85 | 85 |
|
86 | 86 | <!-- 这里可写通用的实现逻辑 -->
|
87 | 87 |
|
| 88 | +**方法一:有序集合 + 优先队列** |
| 89 | + |
| 90 | +题目求的是最繁忙的服务器列表,因此可以想到用**哈希表**记录每个服务器处理的任务数,然后获取所有处理了最大任务数 mx 的服务器列表即可。关键的问题就在于,求出每个任务分配给了哪台服务器处理。 |
| 91 | + |
| 92 | +我们用 有序集合 free 存放所有的空闲服务器,优先队列 busy 存放正在处理请求的服务器的处理结束时间和对应的服务器编号,即二元组 `(end, server)`,优先队列满足队首元素的处理结束时间最小,用一个哈希表 cnt 记录每台服务器处理的任务数。 |
| 93 | + |
| 94 | +当第 i 个请求到达时,如果 busy 不为空,我们循环判断 busy 队首的任务结束时间是否小于等于当前请求的到达时间 `arrival[i]`,即 start。如果是,说明队首任务在此时刻已经处理结束,可以从 busy 队列中移出,循环判断。 |
| 95 | + |
| 96 | +接下来,如果 free 为空,说明当前没有空闲服务器能够处理第 i 个请求,直接 continue 丢弃;否则,查找 free 中大于等于 `i % k` 的第一个服务器,如果查找成功,那么由该服务器来处理该请求,否则,由 free 的第一个服务器(编号最小)来处理。假设该服务器是 server, 那么 `cnt[server]` 加 1,同时将二元组 `(end, server)` 放入优先队列 busy 中,并且将该 server 中有序集合 free 中移出。 |
| 97 | + |
| 98 | +最后,只需要获取 cnt 中的最大值 mx,找出处理了 mx 个任务数的服务器列表,即为答案。 |
| 99 | + |
88 | 100 | <!-- tabs:start -->
|
89 | 101 |
|
90 | 102 | ### **Python3**
|
91 | 103 |
|
92 | 104 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
93 | 105 |
|
94 | 106 | ```python
|
95 |
| - |
| 107 | +from sortedcontainers import SortedList |
| 108 | + |
| 109 | + |
| 110 | +class Solution: |
| 111 | + def busiestServers(self, k: int, arrival: List[int], load: List[int]) -> List[int]: |
| 112 | + free = SortedList(range(k)) |
| 113 | + busy = [] |
| 114 | + cnt = [0] * k |
| 115 | + for i, (start, t) in enumerate(zip(arrival, load)): |
| 116 | + while busy and busy[0][0] <= start: |
| 117 | + free.add(busy[0][1]) |
| 118 | + heappop(busy) |
| 119 | + if not free: |
| 120 | + continue |
| 121 | + j = free.bisect_left(i % k) |
| 122 | + if j == len(free): |
| 123 | + j = 0 |
| 124 | + server = free[j] |
| 125 | + cnt[server] += 1 |
| 126 | + heappush(busy, (start + t, server)) |
| 127 | + free.remove(server) |
| 128 | + |
| 129 | + mx = max(cnt) |
| 130 | + return [i for i, v in enumerate(cnt) if v == mx] |
96 | 131 | ```
|
97 | 132 |
|
98 | 133 | ### **Java**
|
99 | 134 |
|
100 | 135 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
101 | 136 |
|
102 | 137 | ```java
|
| 138 | +class Solution { |
| 139 | + public List<Integer> busiestServers(int k, int[] arrival, int[] load) { |
| 140 | + int[] cnt = new int[k]; |
| 141 | + PriorityQueue<int[]> busy = new PriorityQueue<>(Comparator.comparingInt(a -> a[0])); |
| 142 | + TreeSet<Integer> free = new TreeSet<>(); |
| 143 | + for (int i = 0; i < k; ++i) { |
| 144 | + free.add(i); |
| 145 | + } |
| 146 | + for (int i = 0; i < arrival.length; ++i) { |
| 147 | + int start = arrival[i]; |
| 148 | + int end = start + load[i]; |
| 149 | + while (!busy.isEmpty() && busy.peek()[0] <= start) { |
| 150 | + free.add(busy.poll()[1]); |
| 151 | + } |
| 152 | + if (free.isEmpty()) { |
| 153 | + continue; |
| 154 | + } |
| 155 | + Integer server = free.ceiling(i % k); |
| 156 | + if (server == null) { |
| 157 | + server = free.first(); |
| 158 | + } |
| 159 | + ++cnt[server]; |
| 160 | + busy.offer(new int[]{end, server}); |
| 161 | + free.remove(server); |
| 162 | + } |
| 163 | + int mx = 0; |
| 164 | + for (int v : cnt) { |
| 165 | + mx = Math.max(mx, v); |
| 166 | + } |
| 167 | + List<Integer> ans = new ArrayList<>(); |
| 168 | + for (int i = 0; i < k; ++i) { |
| 169 | + if (cnt[i] == mx) { |
| 170 | + ans.add(i); |
| 171 | + } |
| 172 | + } |
| 173 | + return ans; |
| 174 | + } |
| 175 | +} |
| 176 | +``` |
103 | 177 |
|
| 178 | +### **Go** |
| 179 | + |
| 180 | +```go |
| 181 | +func busiestServers(k int, arrival, load []int) []int { |
| 182 | + free := redblacktree.NewWithIntComparator() |
| 183 | + for i := 0; i < k; i++ { |
| 184 | + free.Put(i, nil) |
| 185 | + } |
| 186 | + busy := hp{} |
| 187 | + cnt := make([]int, k) |
| 188 | + for i, t := range arrival { |
| 189 | + for len(busy) > 0 && busy[0].end <= t { |
| 190 | + free.Put(busy[0].server, nil) |
| 191 | + heap.Pop(&busy) |
| 192 | + } |
| 193 | + if free.Size() == 0 { |
| 194 | + continue |
| 195 | + } |
| 196 | + p, _ := free.Ceiling(i % k) |
| 197 | + if p == nil { |
| 198 | + p = free.Left() |
| 199 | + } |
| 200 | + server := p.Key.(int) |
| 201 | + cnt[server]++ |
| 202 | + heap.Push(&busy, pair{t + load[i], server}) |
| 203 | + free.Remove(server) |
| 204 | + } |
| 205 | + mx := 0 |
| 206 | + for _, v := range cnt { |
| 207 | + if v > mx { |
| 208 | + mx = v |
| 209 | + } |
| 210 | + } |
| 211 | + var ans []int |
| 212 | + for i, v := range cnt { |
| 213 | + if v == mx { |
| 214 | + ans = append(ans, i) |
| 215 | + } |
| 216 | + } |
| 217 | + return ans |
| 218 | +} |
| 219 | + |
| 220 | +type pair struct{ end, server int } |
| 221 | +type hp []pair |
| 222 | + |
| 223 | +func (h hp) Len() int { return len(h) } |
| 224 | +func (h hp) Less(i, j int) bool { return h[i].end < h[j].end } |
| 225 | +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } |
| 226 | +func (h *hp) Push(v interface{}) { *h = append(*h, v.(pair)) } |
| 227 | +func (h *hp) Pop() interface{} { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v } |
104 | 228 | ```
|
105 | 229 |
|
106 | 230 | ### **...**
|
|
0 commit comments