826. 安排工作以达到最大收益
你有 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 == difficulty.length
n == profit.length
m == worker.length
1 <= n, m <= 104
1 <= difficulty[i], profit[i], worker[i] <= 105
- 核心思想还是贪心,尽可能为每个工人分配收益最高的工作。定义 Job 类,保存工作难度以及收益。由于工作难度大的收益能够包含工作难度小的,比如难度为 10 收益为 100 的工作以及难度为 20 收益为 1 的工作,当你的能力为 10 时可以获得 100 的收益,当你能力为 20 时同样可以选择高收益的工作。所以我们按照工作难度从低到高对所有 job 排序,更新当前难度对应的能力可获得的最大收益。这可以省去每次找到所有难度小于等于能力的工作,然后取其中最大收益这一步。
- 最后遍历 worker,每个人都去赚取小于等于能力的最大困难的工作所对应的最大收益即可。
-
class Job{ int d, p; public Job(int d, int p){ this.d = d; this.p = p; } } public int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) { int n = difficulty.length; Job[] jobs = new Job[n]; for(int i = 0; i < n; i++){ jobs[i] = new Job(difficulty[i], profit[i]); } // 排序 Arrays.sort(jobs, (a,b)->a.d-b.d); // 将 p 从对应收益更新为最大收益 int max = jobs[0].p; for(int i = 1; i < n; i++){ max = Math.max(max, jobs[i].p); jobs[i].p = max; } int res = 0; for(int i = 0; i < worker.length; i++){ int j = 0; // 难度小于等于自己的最大 job 中保存了能获取的最大收益 while(j < n && jobs[j].d <= worker[i])j++; if(j > 0)res += jobs[j - 1].p; } return res; }