LC每日一题|20240501 - 2462. 雇佣 K 位工人的总代价
给你一个下标从 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.length <= 10^51 <= costs[i] <= 10^51 <= k, candidates <= costs.length
题目等级:Medium
解题思路
我们仅需要维护一个小顶堆用以获取每轮受雇的工人,同时动态维护雇佣工人的左右边界即可,需要时刻保证左右边界不能碰撞。
AC代码
class Solution {
fun totalCost(costs: IntArray, k: Int, candidates: Int): Long {
val q = PriorityQueue<IntArray>() { a, b -> if (a[0] == b[0]) a[1] - b[1] else a[0] - b[0] }
var left = -1
var right = costs.size
repeat(candidates) {
if (right > left + 1) q.offer(intArrayOf(costs[++left], left))
if (right > left + 1) q.offer(intArrayOf(costs[--right], right))
}
var res = 0L
repeat(k) {
val poll = q.poll()
res += poll[0]
if (left < right - 1) {
if (poll[1] <= left) q.offer(intArrayOf(costs[++left], left))
if (poll[1] >= right) q.offer(intArrayOf(costs[--right], right))
}
}
return res
}
}
时间复杂度:O((k + candidates) log candidates),需要取最多(k + candidates)个元素,同时需要在candidates个元素中取其中最小的元素。
空间复杂度:O(candidates),固定为candidates个元素大小的堆。
碎碎念
劳动节?资本家节!