diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index 1377c3d..67cf65f 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -5426,3 +5426,94 @@ func kthSmallestPrimeFraction(arr []int, k int) []int { return result } ``` + +## day74 2024-05-11 + +### 857. Minimum Cost to Hire K Workers + +There are n workers. You are given two integer arrays quality and wage where quality[i] is the quality of the ith worker and wage[i] is the minimum wage expectation for the ith worker. + +We want to hire exactly k workers to form a paid group. To hire a group of k workers, we must pay them according to the following rules: + +Every worker in the paid group must be paid at least their minimum wage expectation. +In the group, each worker's pay must be directly proportional to their quality. This means if a worker’s quality is double that of another worker in the group, then they must be paid twice as much as the other worker. +Given the integer k, return the least amount of money needed to form a paid group satisfying the above conditions. Answers within 10-5 of the actual answer will be accepted. + +![0511yn4MGoLuDVDe](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0511yn4MGoLuDVDe.png) + +### 题解 + +本题是一道难题, 说实话, 本题只想到了可以用工资和工作量的比值来衡量员工这一步, 因为这种使用比值来决定如何选择的方式在这种同时有某个对象的价值和成本的场景下非常常见. 也就是常说的性价比. 但并没有想出来可以使用优先级队列来一直保存当前k个quality的最小和以及如何更新结果的步骤, 我陷入了一个误区即工资和工作量比值特别高的员工一定不会被选择, 实则不然, 考虑极端情况, 一个平均工作价值为7但工作量为200的员工, 我需要付给他1400, 而一个平均工作价值为200但工作量为1的员工我只需付给他200, 如果之前的员工工作量只有3那我总共需要付800, 显然小于另一个平均工作价值为7的员工. 以及对go优先级队列的实现不是很娴熟. + +本题我查看了他人的题解, 🔗:https://leetcode.cn/problems/minimum-cost-to-hire-k-workers/solutions/1815856/yi-bu-bu-ti-shi-ru-he-si-kao-ci-ti-by-en-1p00/ + +### 代码 + +```go +func mincostToHireWorkers(quality, wage []int, k int) float64 { + + type pair struct{ q, w int } + + pairs := make([]pair, len(quality)) + + for i, q := range quality { + + pairs[i] = pair{q, wage[i]} + + } + + slices.SortFunc(pairs, func(a, b pair) int { return a.w*b.q - b.w*a.q }) // 按照 r 值排序 + + + + h := hp{make([]int, k)} + + sumQ := 0 + + for i, p := range pairs[:k] { + + h.IntSlice[i] = p.q + + sumQ += p.q + + } + + heap.Init(&h) + + + + ans := float64(sumQ*pairs[k-1].w) / float64(pairs[k-1].q) // 选 r 值最小的 k 名工人 + + + + for _, p := range pairs[k:] { // 后面的工人 r 值更大 + + if p.q < h.IntSlice[0] { // 但是 sumQ 可以变小,从而可能得到更优的答案 + + sumQ -= h.IntSlice[0] - p.q + + h.IntSlice[0] = p.q + + heap.Fix(&h, 0) // 更新堆顶 + + ans = min(ans, float64(sumQ*p.w)/float64(p.q)) + + } + + } + + return ans + +} + + + +type hp struct{ sort.IntSlice } + +func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] } // 最大堆 + +func (hp) Push(any) {} + +func (hp) Pop() (_ any) { return } + +```