安排工作以达到最大收益
你有 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.lengthn == profit.lengthm == worker.length1 <= n, m <= 104
思路分析
先统计难度小于等于difficulty[i]时,选择一项工作来做能够获得最大收益;之后每一个工人都可以选择自己能力范围内的,最高收益的工作来做,即为maxProfit[i],但是并不一定是难度最高的工作,而是自己能完成的工作里面,收益最高的一个。
同一个工人,在他的能力范围内,将他安排到收益最高的工作,这样是局部最优的。 对所有的工人都如此安排,可以得到全局最优。
题目的数据量并不大,最大难度以及工人的最大能力都在1e5的范围内。 这样的话,我们可以先把difficulty和profit捆绑起来,即先建一个二维数组a,第一个元素表示难度,第二个表示收益。然后进行排序:如果难度不同,则按难度升序排序;如果难度相同,则按收益升序排序。
算法代码
public int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) {
int n = difficulty.length, m = worker.length;
int[][] a = new int[n][2];
for (int i = 0; i < n; i++) {
a[i][0] = difficulty[i];
a[i][1] = profit[i];
}
Arrays.sort(a, new Comparator < int[] > () {@
Override
public int compare(int[] o1, int[] o2) {
// 如果难度不同,则按难度升序排序;如果难度相同,则按收益升序排序
if (o1[0] == o2[0]) return o1[1] - o2[1];
else return o1[0] - o2[0];
}
});
int[] maxProfit = new int[100001];
int nowProfit = 0;
for (int i = 0; i < n - 1; i++) {
int j = a[i][0];
nowProfit = Math.max(nowProfit, a[i][1]);
while (j < a[i + 1][0]) {
maxProfit[j] = nowProfit;
j++;
}
}
int j = a[n - 1][0];
nowProfit = Math.max(nowProfit, a[n - 1][1]);
while (j <= 100000) {
maxProfit[j] = nowProfit;
j++;
}
int ans = 0;
for (int w: worker) {
ans += maxProfit[w];
}
return ans;
}
结果详情
算法复杂度
- 空间复杂度:
- 时间复杂度:
在掘金(JUEJIN)一起进步,一起成长!