[LeetCode] 857. Minimum Cost to Hire K Workers 雇K個工人的最小花費


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. 

Note:

  1. 1 <= K <= N <= 10000, where N = quality.length = wage.length
  2. 1 <= quality[i] <= 10000
  3. 1 <= wage[i] <= 10000
  4. Answers within 10^-5 of the correct answer will be considered correct.

有N個工人,第i個工人的質量是quality[i],最小工資期盼是wage[i],現在想雇K個工人組成一個支付組,返回所需的最小花費。有兩個條件:

1. K個工人的質量和給他開的工資的比例是相同的。
2. 每個工人都要滿足他的最小期望工資。

解法:最大堆, heapq, PriorityQueue。首先對付工資和質量的比率進行排序wage/quality,同時記錄quality,也就是(wage/quality, quality),代表一個工人情況,比率越大說明工人效率越低。選定的K個人最后要按照相同的比率來支付工資,為了保證每個人的最低工資標准,只能選定比率最高的人的比率來支付工資。每個人的支付工資:wage = ratio * quality,總的支付工資:total wage = ratio * total quality,在ratio相同的情況小,總的quality越小越好。用一個變量result記錄最小花費,初始為最大浮點數。循環排序好的工資比率,用一個變量qsum累加quality,用一個最大堆記錄當前的quality,堆頂是最大的quality,如果堆長度等於K+1,就彈出quality最大的,同時qsum中去掉這個最大值。堆滿足K個工人的時候,每次都計算qsum * ratio,和result比較取小的。

Java:

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

Python:

def mincostToHireWorkers(self, quality, wage, K):
        workers = sorted([float(w) / q, q] for w, q in zip(wage, quality))
        res = float('inf')
        qsum = 0
        heap = []
        for r, q in workers:
            heapq.heappush(heap, -q)
            qsum += q
            if len(heap) > K: qsum += heapq.heappop(heap)
            if len(heap) == K: res = min(res, qsum * r)
        return res

Python:

# Time:   O(nlogn)
# Space : O(n)

import itertools
import heapq

class Solution(object):
    def mincostToHireWorkers(self, quality, wage, K):
        """
        :type quality: List[int]
        :type wage: List[int]
        :type K: int
        :rtype: float
        """
        workers = [[float(w)/q, q] for w, q in itertools.izip(wage, quality)]
        workers.sort()
        result = float("inf")
        qsum = 0
        max_heap = []
        for r, q in workers:
            qsum += q
            heapq.heappush(max_heap, -q)
            if len(max_heap) > K:
                qsum -= -heapq.heappop(max_heap)
            if len(max_heap) == K:
                result = min(result, qsum*r)
        return result  

Python: O(nlogn) time,O(n) space

class Solution(object):
    def mincostToHireWorkers(self, quality, wage, K):
        """
        :type quality: List[int]
        :type wage: List[int]
        :type K: int
        :rtype: float
        """
        # 按比例排序,nlogn
        workers = sorted([float(wage[i])/quality[i], quality[i]] for i in range(len(quality)))
        res,qsum = float('inf'),0
        heap = []

        for i in range(len(workers)):
        	# 選定比例 r
            r,q = workers[i]
            heapq.heappush(heap,-q)
            # qsum始終記錄k個人的quality之和,乘以r即為最后結果
            qsum += q
            if len(heap) > K:
            	# 始終丟棄quality最大的人
                qsum += heapq.heappop(heap)
            if len(heap) == K:
                res = min(res, qsum * r)
        return res

C++:

double mincostToHireWorkers(vector<int> q, vector<int> w, int K) {
        vector<vector<double>> workers;
        for (int i = 0; i < q.size(); ++i)
            workers.push_back({(double)(w[i]) / q[i], (double)q[i]});
        sort(workers.begin(), workers.end());
        double res = DBL_MAX, qsum = 0;
        priority_queue<int> pq;
        for (auto worker: workers) {
            qsum += worker[1], pq.push(worker[1]);
            if (pq.size() > K) qsum -= pq.top(), pq.pop();
            if (pq.size() == K) res = min(res, qsum * worker[0]);
        }
        return res;
    }

C++:

// Time:  O(nlogn)
// Space: O(n)
class Solution {
public:
    double mincostToHireWorkers(vector<int>& quality, vector<int>& wage, int K) {
        vector<pair<double, int>> workers;
        for (int i = 0; i < quality.size(); ++i) {
            workers.emplace_back(static_cast<double>(wage[i]) / quality[i],
                                 quality[i]);
        }
        sort(workers.begin(), workers.end());
        auto result = numeric_limits<double>::max();
        auto sum = 0.0;
        priority_queue<int> max_heap;
        for (const auto& worker: workers) {
            sum += worker.second;
            max_heap.emplace(worker.second);
            if (max_heap.size() > K) {
                sum -= max_heap.top(), max_heap.pop();
            }
            if (max_heap.size() == K) {
                result = min(result, sum * worker.first);
            }
        }
        return result;
    }
};

  

 

All LeetCode Questions List 題目匯總

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM