题目链接
Leetcode.826 安排工作以达到最大收益 Rating : 1709
题目描述
你有 n
个工作和 m
个工人。给定三个数组: difficulty, profit 和 worker
,其中:
difficulty[i]
表示第i
个工作的难度,profit[i]
表示第i
个工作的收益。worker[i]
是第i
个工人的能力,即该工人只能完成难度小于等于worker[i]
的工作。
每个工人 最多 只能安排 一个 工作,但是一个工作可以 完成多次 。
- 举个例子,如果 3 个工人都尝试完成一份报酬为 $1 的同样工作,那么总收益为 $3 。如果一个工人不能完成任何工作,他的收益为 $0 。
返回 在把工人分配到工作岗位后,我们所能获得的最大利润 。
示例 1:
输入: difficulty = [2,4,6,8,10], profit = [10,20,30,40,50], worker = [4,5,6,7]
输出: 100
解释: 工人被分配的工作难度是 [4,4,6,6] ,分别获得 [20,20,30,30] 的收益。
示例 2:
输入: difficulty = [85,47,57], profit = [24,66,99], worker = [40,25,25]
输出: 0
提示:
- n = = d i f f i c u l t y . l e n g t h n == difficulty.length n==difficulty.length
- n = = p r o f i t . l e n g t h n == profit.length n==profit.length
- m = = w o r k e r . l e n g t h m == worker.length m==worker.length
- 1 < = n , m < = 1 0 4 1 <= n, m <= 10^4 1<=n,m<=104
- 1 < = d i f f i c u l t y [ i ] , p r o f i t [ i ] , w o r k e r [ i ] < = 1 0 5 1 <= difficulty[i], profit[i], worker[i] <= 10^5 1<=difficulty[i],profit[i],worker[i]<=105
分析:
我们先用一个集合 v
来装(difficulty,profit)
这样的二元组。
接着再对 集合v
按 difficulty
排序。
例如: difficulty = [85,47,57], profit = [24,66,99]
。排序后的集合就为 v = [ [47,66] , [57,99] , [85,25] ]
。
如果有一个工人的能力是 100
,那么他应该选择的就是这一项 [57,99]
,即最大收益 99
。
注意: 实际上我们只关心每一个工人能取得的最大收益,并不关心具体要选择哪一个难度的工作。
将排序后的集合v
稍加处理,让其只记录前面任务的最大收益,即 v = [ [47,66] , [57,99] , [85,99] ]
。这样的话,我们就可以使用 二分 的方式,求得第一个小于等于某一个工人极限的最大收益。
时间复杂度: O ( n ∗ l o g n ) O(n*logn) O(n∗logn)
C++代码:
using PII = pair<int,int>;
class Solution {
public:
int maxProfitAssignment(vector<int>& difficulty, vector<int>& profit, vector<int>& worker) {
int n = difficulty.size();
vector<PII> a;
for(int i = 0;i < n;i++){
a.push_back({difficulty[i],profit[i]});
}
//pair<int,int> 是默认先按第一个参数排序,第一个参数相等的话再按第二个参数排序
sort(a.begin(),a.end());
//只记录到当前难度的最大收益
for(int i = 1;i < n;i++){
a[i].second = max(a[i].second,a[i-1].second);
}
int ans = 0;
for(auto x:worker){
//对于每一个工人,直接二分求最大的收益
int l = 0,r = n - 1;
while(l < r){
int mid = (l + r + 1) >> 1;
if(a[mid].first <= x) l = mid;
else r = mid - 1;
}
if(a[l].first <= x) ans += a[l].second;
}
return ans;
}
};
Java代码:
class Solution {
public int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) {
List<int[]> list = new ArrayList<>();
int n = difficulty.length;
for(int i = 0;i < n;i++) list.add(new int[]{difficulty[i],profit[i]});
//按 difficulty 从小到大排序
Collections.sort(list,(a,b)->(a[0] - b[0]));
for(int i = 1;i < n;i++){
list.get(i)[1] = Math.max(list.get(i)[1],list.get(i-1)[1]);
}
int ans = 0;
for(int x:worker){
int l = 0,r = n - 1;
while(l<r){
int mid = (l + r + 1) >> 1;
if(list.get(mid)[0] <= x) l = mid;
else r = mid - 1;
}
if(list.get(l)[0] <= x) ans += list.get(l)[1];
}
return ans;
}
}