LeetCode[Hard]------857. Minimum Cost To Hire K Workers

问题描述

There are N workers. The i-th worker has a quality[i] and a minimum wage expectation wage[i].

Now we want to hire exactly K workers to form a paid group. When hiring a group of K workers, we must pay them according to the following rules:

  1. Every worker in the paid group should be paid in the ratio of their quality compared to other workers in the paid group.
  2. Every worker in the paid group must be paid at least their minimum wage expectation.

Return the least amount of money needed to form a paid group satisfying the above conditions.

Example 1:

Input: quality = [10,20,5], wage = [70,50,30], K = 2
Output: 105.00000
Explanation: We pay 70 to 0-th worker and 35 to 2-th worker.

Example 2:

Input: quality = [3,1,10,10,1], wage = [4,8,2,2,7], K = 3
Output: 30.66667
Explanation: We pay 4 to 0-th worker, 13.33333 to 2-th and 3-th workers seperately.


简单翻译一下,现在要雇佣K名工人,每个工人有自己的能力值quality和对期望的薪水wage,但是他们实际的薪水必须满足两个条件

  1. 实际薪水必须和他们的能力成正比。
  2. 每个被雇佣的工人必须满足他们最低的薪水期望

要求返回雇佣K个工人最小的支付薪水。

思路:

首先要对题目所给的rules有精确的理解,简单来说就是1份quality,1份wage,而且每个人都有满足其最小wage expectation。

我的第一印象是按wage大小对workers进行排序,把最小的K个wage的加起来即可,因为题目中没有对quality的限制。但这么想的话根本就是个easy问题。再三考虑之后发现,发钱时并不是按wage数组发的,而是和wage/quality这个比值有关。因为根据rule1,worker i,j 的quality[i]:quality[j] == wage[i]: wage[j]的,因此 quality[i]:wage[i] == quality[j]:wage[j],也就是说wage/quality 的ratio对于每个worker来说都一样!!

于是我有了思路,通过这个ratio构建worker数组,并从小到大sort,然后我们取前K个worker,他们的ratio必须是ratio最大的那个 worker的,也就是最近取的那个worker,此时的wage总和就是总的quality × 最近取的worker的ratio。

做到这里感觉程序就可以结束了,因为ratio这里是最小的。但是如果我们继续遍历worker,ratio虽然增大但是quality的总和可能会减小。所以我们需要遍历所有worker,保证hire window的size始终为K。

问题又来了,如何保证K个worker的quality在遍历时持续remove最大的quality? PriorityQueue 可以完美解决这个问题,只需要add进负的worker quality,此时poll出的就是最大的quality。

代码:

public double mincostToHireWorkers(int[] quality, int[] wage, int K) {
		double[][] workers = new double[quality.length][2];
        for (int i = 0; i < quality.length; ++i)
            workers[i] = new double[]{(double)(wage[i]) / quality[i], (double)quality[i]};
        Arrays.sort(workers, (a, b) -> Double.compare(a[0], b[0]));
        double res = Double.MAX_VALUE, qsum = 0;
        PriorityQueue<Double> l = new PriorityQueue<>();
        for (double[] worker: workers) {
            qsum += worker[1];
            l.add(-worker[1]);
            if (l.size() > K) qsum += l.poll();
            if (l.size() == K) res = Math.min(res, qsum * worker[0]);
        }
        return res;
    }      

仅用于个人的学习理解,如需转载,请标明出处:
https://blog.csdn.net/sc19951007/article/details/83684434

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值