64
64
65
65
### 方法一:优先队列(小根堆)
66
66
67
- 我们用一个优先队列(小根堆)维护当前的候选工人,用变量 $i$ 和 $j$ 标记最前面工人的最大小标和最后面工人的最小下标。初始时 $i = candidates - 1$,而 $j = n - candidates$ 。
67
+ 我们首先判断 $candidates \times 2$ 是否大于等于 $n$,如果是,我们直接返回前 $k$ 个最小的工人的代价之和 。
68
68
69
- 我们先将前面 $candidates$ 个工人的代价放入优先队列中,再将最后面 $candidates$ 个工人的代价放入优先队列中,放入之前需要判断根据 $i$ 或 $j$ 是否已经在优先队列中,如果已经在优先队列中,则不需要再放入 。
69
+ 否则,我们使用一个小根堆 $pq$ 来维护前 $candidates$ 个工人和后 $candidates$ 个工人的代价 。
70
70
71
- 循环 $k$ 次,每次从优先队列中取出最小代价的工人,累加代价。如果当前取出的工人下标 $x$ 在最前面工人的下标范围 $ [ 0,..i ] $ 中,则将 $i$ 向右移动一位,然后判断是否要将 $i$ 对应的工人代价放入优先队列中;如果取出的下标在最后面工人的下标范围 $ [ j,..n-1 ] $ 中,则将 $j$ 向左移动一位,然后判断是否要将 $j$ 对应的工人代价放入优先队列中 。
71
+ 我们首先将前 $candidates$ 个工人的代价以及对应的下标加入小根堆 $pq$ 中,然后将后 $candidates$ 个工人的代价以及对应的下标加入小根堆 $pq$ 中。用两个指针 $l$ 和 $r$ 分别指向前后待选工人的下标,初始时 $l = candidates$, $r = n - candidates - 1$ 。
72
72
73
- 遍历结束后,将累加的代价作为答案返回 。
73
+ 然后我们进行 $k$ 次循环,每次从小根堆 $pq$ 中取出代价最小的工人,将其代价加入答案,如果 $l > r$,说明前后待选工人已经全部被选完,直接跳过。否则,如果当前工人的下标小于 $l$,说明是前面的工人,我们将第 $l$ 个工人的代价以及下标加入小根堆 $pq$ 中,然后 $l$ 加一;否则,我们将第 $r$ 个工人的代价以及下标加入小根堆 $pq$ 中,然后 $r$ 减一 。
74
74
75
- 时间复杂度 $O(n\times \log n)$。其中 $n$ 为数组 $costs$ 的长度。
75
+ 循环结束后,返回答案即可。
76
+
77
+ 时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 $costs$ 的长度。
76
78
77
79
<!-- tabs:start -->
78
80
79
81
``` python
80
82
class Solution :
81
83
def totalCost (self , costs : List[int ], k : int , candidates : int ) -> int :
82
- q = []
83
84
n = len (costs)
84
- i, j = candidates - 1 , n - candidates
85
- for h in range (candidates):
86
- q.append((costs[h], h))
87
- for h in range (n - candidates, n):
88
- if h > i:
89
- q.append((costs[h], h))
90
- heapify(q)
85
+ if candidates * 2 >= n:
86
+ return sum (sorted (costs)[:k])
87
+ pq = []
88
+ for i, c in enumerate (costs[:candidates]):
89
+ heappush(pq, (c, i))
90
+ for i in range (n - candidates, n):
91
+ heappush(pq, (costs[i], i))
92
+ heapify(pq)
93
+ l, r = candidates, n - candidates - 1
91
94
ans = 0
92
95
for _ in range (k):
93
- c, x = heappop(q )
96
+ c, i = heappop(pq )
94
97
ans += c
95
- if x <= i :
96
- i += 1
97
- if i < j :
98
- heappush(q , (costs[i ], i ))
99
- if x >= j:
100
- j -= 1
101
- if i < j:
102
- heappush(q, (costs[j], j))
98
+ if l > r :
99
+ continue
100
+ if i < l :
101
+ heappush(pq , (costs[l ], l ))
102
+ l += 1
103
+ else :
104
+ heappush(pq, (costs[r], r))
105
+ r -= 1
103
106
return ans
104
107
```
105
108
106
109
``` java
107
110
class Solution {
108
111
public long totalCost (int [] costs , int k , int candidates ) {
109
- PriorityQueue<int[]> q = new PriorityQueue<> ((a, b) - > {
110
- if (a[0 ] == b[0 ]) {
111
- return a[1 ] - b[1 ];
112
- }
113
- return a[0 ] - b[0 ];
114
- });
115
112
int n = costs. length;
116
- int i = candidates - 1 , j = n - candidates;
117
- for (int h = 0 ; h < candidates; ++ h) {
118
- q. offer(new int [] {costs[h], h});
119
- }
120
- for (int h = n - candidates; h < n; ++ h) {
121
- if (h > i) {
122
- q. offer(new int [] {costs[h], h});
113
+ long ans = 0 ;
114
+ if (candidates * 2 >= n) {
115
+ Arrays . sort(costs);
116
+ for (int i = 0 ; i < k; ++ i) {
117
+ ans += costs[i];
123
118
}
119
+ return ans;
124
120
}
125
- long ans = 0 ;
121
+ PriorityQueue<int[]> pq
122
+ = new PriorityQueue<> ((a, b) - > a[0 ] == b[0 ] ? a[1 ] - b[1 ] : a[0 ] - b[0 ]);
123
+ for (int i = 0 ; i < candidates; ++ i) {
124
+ pq. offer(new int [] {costs[i], i});
125
+ pq. offer(new int [] {costs[n - i - 1 ], n - i - 1 });
126
+ }
127
+ int l = candidates, r = n - candidates - 1 ;
126
128
while (k-- > 0 ) {
127
- var e = q. poll();
128
- int c = e[0 ], x = e[1 ];
129
- ans += c;
130
- if (x <= i) {
131
- if (++ i < j) {
132
- q. offer(new int [] {costs[i], i});
133
- }
129
+ var p = pq. poll();
130
+ ans += p[0 ];
131
+ if (l > r) {
132
+ continue ;
134
133
}
135
- if (x >= j ) {
136
- if ( -- j > i) {
137
- q . offer( new int [] {costs[j], j});
138
- }
134
+ if (p[ 1 ] < l ) {
135
+ pq . offer( new int [] {costs[l], l ++ });
136
+ } else {
137
+ pq . offer( new int [] {costs[r], r -- });
139
138
}
140
139
}
141
140
return ans;
@@ -144,31 +143,33 @@ class Solution {
144
143
```
145
144
146
145
``` cpp
147
- using pii = pair<int , int >;
148
-
149
146
class Solution {
150
147
public:
151
148
long long totalCost(vector<int >& costs, int k, int candidates) {
152
- priority_queue<pii, vector<pii >, greater<pii >> q;
153
149
int n = costs.size();
154
- int i = candidates - 1, j = n - candidates;
155
- for (int h = 0; h < candidates; ++h) q.push({costs[ h] , h});
156
- for (int h = n - candidates; h < n; ++h)
157
- if (h > i) q.push({costs[ h] , h});
150
+ if (candidates * 2 > n) {
151
+ sort(costs.begin(), costs.end());
152
+ return accumulate(costs.begin(), costs.begin() + k, 0LL);
153
+ }
154
+ using pii = pair<int, int>;
155
+ priority_queue<pii, vector<pii >, greater<pii >> pq;
156
+ for (int i = 0; i < candidates; ++i) {
157
+ pq.emplace(costs[ i] , i);
158
+ pq.emplace(costs[ n - i - 1] , n - i - 1);
159
+ }
158
160
long long ans = 0;
161
+ int l = candidates, r = n - candidates - 1;
159
162
while (k--) {
160
- auto [ c, x] = q.top();
161
- q.pop();
162
- ans += c;
163
- if (x <= i) {
164
- if (++i < j) {
165
- q.push({costs[ i] , i});
166
- }
163
+ auto [ cost, i] = pq.top();
164
+ pq.pop();
165
+ ans += cost;
166
+ if (l > r) {
167
+ continue;
167
168
}
168
- if (x >= j ) {
169
- if (--j > i) {
170
- q.push({costs [ j ] , j});
171
- }
169
+ if (i < l ) {
170
+ pq.emplace(costs [ l ] , l++);
171
+ } else {
172
+ pq.emplace(costs [ r ] , r--);
172
173
}
173
174
}
174
175
return ans;
@@ -177,48 +178,80 @@ public:
177
178
```
178
179
179
180
```go
180
- func totalCost(costs []int, k int, candidates int) int64 {
181
- q := hp{}
181
+ func totalCost(costs []int, k int, candidates int) (ans int64) {
182
182
n := len(costs)
183
- i, j := candidates-1, n-candidates
184
- for h := 0; h < candidates; h++ {
185
- heap.Push(&q, pair{costs[h], h})
186
- }
187
- for h := n - candidates; h < n; h++ {
188
- if h > i {
189
- heap.Push(&q, pair{costs[h], h})
183
+ if candidates*2 > n {
184
+ sort.Ints(costs)
185
+ for _, x := range costs[:k] {
186
+ ans += int64(x)
190
187
}
188
+ return
191
189
}
192
- ans := 0
193
- for k > 0 {
194
- p := heap.Pop(&q).(pair)
195
- c, x := p.c, p.x
196
- ans += c
197
- if x <= i {
198
- i++
199
- if i < j {
200
- heap.Push(&q, pair{costs[i], i})
201
- }
190
+ pq := hp{}
191
+ for i, x := range costs[:candidates] {
192
+ heap.Push(&pq, pair{x, i})
193
+ heap.Push(&pq, pair{costs[n-i-1], n - i - 1})
194
+ }
195
+ l, r := candidates, n-candidates-1
196
+ for ; k > 0; k-- {
197
+ p := heap.Pop(&pq).(pair)
198
+ ans += int64(p.cost)
199
+ if l > r {
200
+ continue
202
201
}
203
- if x >= j {
204
- j--
205
- if i < j {
206
- heap.Push(&q, pair{costs[j], j})
207
- }
202
+ if p.i < l {
203
+ heap.Push(&pq, pair{costs[l], l})
204
+ l++
205
+ } else {
206
+ heap.Push(&pq, pair{costs[r], r})
207
+ r--
208
208
}
209
- k--
210
209
}
211
- return int64(ans)
210
+ return
212
211
}
213
212
214
- type pair struct{ c, x int }
213
+ type pair struct{ cost, i int }
215
214
type hp []pair
216
215
217
- func (h hp) Len() int { return len(h) }
218
- func (h hp) Less(i, j int) bool { return h[i].c < h[j].c || h[i].c == h[j].c && h[i].x < h[j].x }
219
- func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
220
- func (h *hp) Push(v any) { *h = append(*h, v.(pair)) }
221
- func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
216
+ func (h hp) Len() int { return len(h) }
217
+ func (h hp) Less(i, j int) bool {
218
+ return h[i].cost < h[j].cost || (h[i].cost == h[j].cost && h[i].i < h[j].i)
219
+ }
220
+ func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
221
+ func (h *hp) Push(v any) { *h = append(*h, v.(pair)) }
222
+ func (h *hp) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
223
+ ```
224
+
225
+ ``` ts
226
+ function totalCost(costs : number [], k : number , candidates : number ): number {
227
+ const n = costs .length ;
228
+ if (candidates * 2 >= n ) {
229
+ costs .sort ((a , b ) => a - b );
230
+ return costs .slice (0 , k ).reduce ((acc , x ) => acc + x , 0 );
231
+ }
232
+ const pq = new PriorityQueue ({
233
+ compare : (a , b ) => (a [0 ] === b [0 ] ? a [1 ] - b [1 ] : a [0 ] - b [0 ]),
234
+ });
235
+ for (let i = 0 ; i < candidates ; ++ i ) {
236
+ pq .enqueue ([costs [i ], i ]);
237
+ pq .enqueue ([costs [n - i - 1 ], n - i - 1 ]);
238
+ }
239
+ let [l, r] = [candidates , n - candidates - 1 ];
240
+ let ans = 0 ;
241
+ while (k -- ) {
242
+ const [cost, i] = pq .dequeue ()! ;
243
+ ans += cost ;
244
+ if (l > r ) {
245
+ continue ;
246
+ }
247
+ if (i < l ) {
248
+ pq .enqueue ([costs [l ], l ++ ]);
249
+ } else {
250
+ pq .enqueue ([costs [r ], r -- ]);
251
+ }
252
+ }
253
+ return ans ;
254
+ }
222
255
```
223
256
224
257
<!-- tabs: end -->
0 commit comments