LeetCode 826. Most Profit Assigning Work
今天算法群里出的一道题,题目不难,但是这道题有多种解法,而且注意分析每种解法的时间复杂度,不能超时
题目:
We have jobs: difficulty[i] is the difficulty of the ith job, and profit[i] is the profit of the ith job.
Now we have some workers. worker[i] is the ability of the ith worker, which means that this worker can only complete a job with difficulty at most worker[i].
Every worker can be assigned at most one job, but one job can be completed multiple times.
For example, if 3 people attempt the same job that pays $1, then the total profit will be $3. If a worker cannot complete any job, his profit is $0.
What is the most profit we can make?
给定一些工作难度和每个工作的利润,以及每个工人能够完成的工作的最大难度,每个工人只能分配一个工作,到那时一个工作可以背多次完成,求怎么分配工作才能使得利润最大
分析:
- 总的思路是贪心求解,会有O(n3)的复杂度,关键是想着怎么减少复杂度,用TreeMap可以到复杂度O(n2logn),优化下TreeMap能到O(nlogn),Sort+双指针的复杂度也是O(nlogn)
代码
- 法一:
暴力TreeMap---O(n^2logn)
public int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) {
int res = 0;
TreeMap<Integer, Integer> map = new TreeMap<>();
for (int i = 0; i < difficulty.length; i++) {
map.put(difficulty[i], i);
}
for (int w : worker) {
Integer low = map.floorKey(w);
if (low == null) continue;
int index = map.get(low);
for (int i = 0; i < difficulty.length; i++) {
if (difficulty[i] <= low && profit[i] > profit[index]) {
index = i;
}
}
res += profit[index];
}
return res;
}
- 法二:
优化的TreeMap---O(nlogn)
- 如果TreeMap里面保存的是每个difficulty[i] 对应的最大的profit,则就可以直接找floorKey对应的value就是对应的要找的value;
那么只需要再遍历一次TreeMap,将最大的到目前key位置最大的value放进去就行了
- 如果TreeMap里面保存的是每个difficulty[i] 对应的最大的profit,则就可以直接找floorKey对应的value就是对应的要找的value;
public int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) {
TreeMap<Integer, Integer> map = new TreeMap<>();
for (int i = 0; i < difficulty.length; i++) {
map.put(difficulty[i], Math.max(map.getOrDefault(difficulty[i], 0), profit[i]));
}
int max = 0;
for (int key : map.keySet()) { //将最大的到目前key位置最大的value放进去
max = Math.max(max, map.get(key));
map.put(key, max);
}
int res = 0;
for (int w : worker) {
Integer low = map.floorKey(w);
if (low == null) continue;
res += map.get(low);
}
return res;
}
- 法三:
Sort + 双指针---O(nlogn)
- 思路就是先将 difficulty和profit组成pair,然后再将list和worker 从小到大排序,然后遍历worker,更新tempMaxProfit,得到总的maxProfit
class Solution {
public int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) {
List<int[]> list = new ArrayList<>();
for (int i = 0; i < difficulty.length; i++) {
list.add(new int[]{difficulty[i], profit[i]});
}
Collections.sort(list, (a, b) -> {return a[0] - b[0];});
Arrays.sort(worker);
int res = 0, tmpMaxProfit = 0;
//i, j同向双指针移动,更新到目前的tmpMaxProfit
for (int i = 0, j = 0; i < worker.length; i++) {
while (j < list.size() && list.get(j)[0] <= worker[i]) {
tmpMaxProfit = Math.max(tmpMaxProfit, list.get(j)[1]);
j++;
}
//此时tmpMaxProfit是前面所有difficulty小于worker[i]的最大的proifit
res += tmpMaxProfit;
}
return res;
}
}