LC每日一题|20240502 - 857. 雇佣 K 名工人的最低成本
有
n名工人。 给定两个数组quality和wage,其中,quality[i]表示第i名工人的工作质量,其最低期望工资为wage[i]。现在我们想雇佣
k名工人组成一个工资组。 在雇佣 一组k名工人时,我们必须按照下述规则向他们支付工资:
- 对工资组中的每名工人,应当按其工作质量与同组其他工人的工作质量的比例来支付工资。
- 工资组中的每名工人至少应当得到他们的最低期望工资。
给定整数
k,返回 组成满足上述条件的付费群体所需的最小金额 。在实际答案的10^-5以内的答案将被接受。
提示:
n == quality.length == wage.length1 <= k <= n <= 10^41 <= quality[i], wage[i] <= 10^4
题目等级:Hard
解题思路
友情提示,千万不要把你自己带入到这道题中,小心血压⬆️ ⬆️ ⬆️。
由于题目中说工资是按照工作质量成比例发放的,所以最终每个人所拿到的单位薪资,即 cost / quality,是相同的。就此我们可以得知,对于任意一组工人来说,所付金额 = 组内所有人的质量和 * 其中性价比最低者的单位薪资。
我们可以先处理出每个工人期望的单位薪资,开一个小顶堆进行排序(实际上就是性价比的反序)。然后再用一个小顶堆维护组内每个人的质量,每次加入一个新人的时候,都将原有的质量最高的老人踢出去,因为他们花钱最多。最后动态维护所付金额的最小值返回即可。
AC代码
class Solution {
fun mincostToHireWorkers(quality: IntArray, wage: IntArray, k: Int): Double {
val vc = DoubleArray(quality.size) { 1.0 * wage[it] / quality[it] }
val v = PriorityQueue<Int>() { a, b -> vc[a].compareTo(vc[b]) }
val qq = PriorityQueue<Int>() { a, b -> quality[b] - quality[a] }
for (i in quality.indices) v.offer(i)
var sumQuality = 0
var minResult = Double.MAX_VALUE
var poll = 0
repeat(k) {
poll = v.poll()
sumQuality += quality[poll]
qq.offer(poll)
}
var min = sumQuality * vc[poll]
for (i in k until quality.size) {
poll = v.poll()
qq.offer(poll)
val qp = qq.poll()
sumQuality -= quality[qp]
sumQuality += quality[poll]
min = Math.min(min, sumQuality * vc[poll])
}
return min
}
}
时间复杂度:O(nlogn),用于堆排序。
空间复杂度:O(n),需要维护两个堆。
碎碎念
这个资本家根本不关心这帮人能做多少东西,他只关注三件事情:
- 少花钱
- 凑人头
- 防内斗
(是不是有点像你的leader?
请不要对号入座,如有雷同,实属巧合~