合法的pay group里所有worker的比例是一样的,即 wage1/wage2 = quality1/quality2
推出 wage1/quality1 = wage2/quality2。
这就好办了,定义 ratio_i = wage_i/quality_i。对于一个group,ratio一定是所有人中最大的那个。
对于一个大小为k的group,需要pay的钱就是 Σ_k quality_i * 最大的ratio。
为了避免每次扫一遍group找到最大的ratio,我们根据ratio排序,根据ratio从小到大考虑。同时我们建立一个大小为k的大顶堆,并保证当前堆里的元素除了当前ratio,是最小的k-1个元素。
和 top k 问题用小顶堆一样,这里用大顶堆可以找到最小的k个元素,从而这k个元素的和也是最小的。
class Solution { public: struct Worker { int quality, wage; double ratio; Worker(int q, int w):quality(q),wage(w){ ratio = double(wage)/quality; } }; double mincostToHireWorkers(vector<int>& quality, vector<int>& wage, int K) { int n=quality.size(); vector<Worker> vec; for (int i=0;i<n;++i){ vec.push_back(Worker(quality[i],wage[i])); } sort(vec.begin(),vec.end(),[](const Worker &a, const Worker &b){ return a.ratio<b.ratio; }); // max heap accourding to quality auto cmp=[](const Worker &a, const Worker &b){ return a.quality < b.quality; }; priority_queue<Worker,vector<Worker>,decltype(cmp)> q(cmp); double sum=0, res=INT_MAX; // sum - sum of quality for (Worker worker:vec){ if (q.size()>=K){ sum -= q.top().quality; q.pop(); } q.push(worker); sum += worker.quality; if (q.size()==K) res=min(res, sum*worker.ratio); } return res; } };
时间复杂度 O(nlogn)