1. 程式人生 > >LeetCode[Hard]------857. Minimum Cost To Hire K Workers

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;
    }