给你一个下标从 0 开始的整数数组 costs
,其中 costs[i]
是雇佣第 i
位工人的代价。
同时给你两个整数 k
和 candidates
。我们想根据以下规则恰好雇佣 k
位工人:
- 总共进行
k
轮雇佣,且每一轮恰好雇佣一位工人。 - 在每一轮雇佣中,从最前面
candidates
和最后面candidates
人中选出代价最小的一位工人,如果有多位代价相同且最小的工人,选择下标更小的一位工人。- 比方说,
costs = [3,2,7,7,1,2]
且candidates = 2
,第一轮雇佣中,我们选择第4
位工人,因为他的代价最小[3,2,7,7,1,2]
。 - 第二轮雇佣,我们选择第
1
位工人,因为他们的代价与第4
位工人一样都是最小代价,而且下标更小,[3,2,7,7,2]
。注意每一轮雇佣后,剩余工人的下标可能会发生变化。
- 比方说,
- 如果剩余员工数目不足
candidates
人,那么下一轮雇佣他们中代价最小的一人,如果有多位代价相同且最小的工人,选择下标更小的一位工人。 - 一位工人只能被选择一次。
返回雇佣恰好 k
位工人的总代价。
示例 1:
输入:costs = [17,12,10,2,7,2,11,20,8], k = 3, candidates = 4 输出:11 解释:我们总共雇佣 3 位工人。总代价一开始为 0 。 - 第一轮雇佣,我们从 [17,12,10,2,7,2,11,20,8] 中选择。最小代价是 2 ,有两位工人,我们选择下标更小的一位工人,即第 3 位工人。总代价是 0 + 2 = 2 。 - 第二轮雇佣,我们从 [17,12,10,7,2,11,20,8] 中选择。最小代价是 2 ,下标为 4 ,总代价是 2 + 2 = 4 。 - 第三轮雇佣,我们从 [17,12,10,7,11,20,8] 中选择,最小代价是 7 ,下标为 3 ,总代价是 4 + 7 = 11 。注意下标为 3 的工人同时在最前面和最后面 4 位工人中。 总雇佣代价是 11 。
示例 2:
输入:costs = [1,2,4,1], k = 3, candidates = 3 输出:4 解释:我们总共雇佣 3 位工人。总代价一开始为 0 。 - 第一轮雇佣,我们从 [1,2,4,1] 中选择。最小代价为 1 ,有两位工人,我们选择下标更小的一位工人,即第 0 位工人,总代价是 0 + 1 = 1 。注意,下标为 1 和 2 的工人同时在最前面和最后面 3 位工人中。 - 第二轮雇佣,我们从 [2,4,1] 中选择。最小代价为 1 ,下标为 2 ,总代价是 1 + 1 = 2 。 - 第三轮雇佣,少于 3 位工人,我们从剩余工人 [2,4] 中选择。最小代价是 2 ,下标为 0 。总代价为 2 + 2 = 4 。 总雇佣代价是 4 。
提示:
1 <= costs.length <= 105
1 <= costs[i] <= 105
1 <= k, candidates <= costs.length
方法一:优先队列(小根堆)
我们用一个优先队列(小根堆)维护当前的候选工人,用变量
我们先将前面
循环
遍历结束后,将累加的代价作为答案返回。
时间复杂度
class Solution:
def totalCost(self, costs: List[int], k: int, candidates: int) -> int:
q = []
n = len(costs)
i, j = candidates - 1, n - candidates
for h in range(candidates):
q.append((costs[h], h))
for h in range(n - candidates, n):
if h > i:
q.append((costs[h], h))
heapify(q)
ans = 0
for _ in range(k):
c, x = heappop(q)
ans += c
if x <= i:
i += 1
if i < j:
heappush(q, (costs[i], i))
if x >= j:
j -= 1
if i < j:
heappush(q, (costs[j], j))
return ans
class Solution {
public long totalCost(int[] costs, int k, int candidates) {
PriorityQueue<int[]> q = new PriorityQueue<>((a, b) -> {
if (a[0] == b[0]) {
return a[1] - b[1];
}
return a[0] - b[0];
});
int n = costs.length;
int i = candidates - 1, j = n - candidates;
for (int h = 0; h < candidates; ++h) {
q.offer(new int[] {costs[h], h});
}
for (int h = n - candidates; h < n; ++h) {
if (h > i) {
q.offer(new int[] {costs[h], h});
}
}
long ans = 0;
while (k-- > 0) {
var e = q.poll();
int c = e[0], x = e[1];
ans += c;
if (x <= i) {
if (++i < j) {
q.offer(new int[] {costs[i], i});
}
}
if (x >= j) {
if (--j > i) {
q.offer(new int[] {costs[j], j});
}
}
}
return ans;
}
}
using pii = pair<int, int>;
class Solution {
public:
long long totalCost(vector<int>& costs, int k, int candidates) {
priority_queue<pii, vector<pii>, greater<pii>> q;
int n = costs.size();
int i = candidates - 1, j = n - candidates;
for (int h = 0; h < candidates; ++h) q.push({costs[h], h});
for (int h = n - candidates; h < n; ++h) if (h > i) q.push({costs[h], h});
long long ans = 0;
while (k--) {
auto [c, x] = q.top();
q.pop();
ans += c;
if (x <= i) {
if (++i < j) {
q.push({costs[i], i});
}
}
if (x >= j) {
if (--j > i) {
q.push({costs[j], j});
}
}
}
return ans;
}
};
func totalCost(costs []int, k int, candidates int) int64 {
q := hp{}
n := len(costs)
i, j := candidates-1, n-candidates
for h := 0; h < candidates; h++ {
heap.Push(&q, pair{costs[h], h})
}
for h := n - candidates; h < n; h++ {
if h > i {
heap.Push(&q, pair{costs[h], h})
}
}
ans := 0
for k > 0 {
p := heap.Pop(&q).(pair)
c, x := p.c, p.x
ans += c
if x <= i {
i++
if i < j {
heap.Push(&q, pair{costs[i], i})
}
}
if x >= j {
j--
if i < j {
heap.Push(&q, pair{costs[j], j})
}
}
k--
}
return int64(ans)
}
type pair struct{ c, x int }
type hp []pair
func (h hp) Len() int { return len(h) }
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 }
func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *hp) Push(v interface{}) { *h = append(*h, v.(pair)) }
func (h *hp) Pop() interface{} { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }