题目链接
你可以安排的最多任务数目
题目描述
![](https://i-blog.csdnimg.cn/direct/628b3212a41a446db00cd1c8b38e5bdd.png)
![](https://i-blog.csdnimg.cn/direct/e6d9d16f644e42e8be92c02fdfb3ee0c.png)
![](https://i-blog.csdnimg.cn/direct/fa2a99f82c144ea9b8058904c6f4a42c.png)
注意点
- 1 <= n, m <= 5 * 10^4
- 0 <= pills <= m
- 0 <= tasks[i], workers[j], strength <= 10^9
- 每个工人只能完成一个任务
- 每个工人最多只能使用一片药丸
解答思路
- 参照题解使用二分查找 + 贪心算法解决本题
- 二分查找的思想是找到可以安排的最多任务数目k,初始认为最少能完成的任务数目是0,最多能完成的任务数目是Math.min(tasks.length, workers.length),根据中间值不断二分找到k
- 贪心算法的思想是假设可以安排的最多任务数目一定是mid,那么应该安排力量最大的k个工人完成需要力量最小的k个任务,具体应该怎么分配任务?从最大的任务task遍历:
- 如果此时力量最大的工人能够完成task,则贪心地认为该工人直接完成task
- 如果此时力量最大的工人无法完成task,且还有药丸,则贪心地认为加上药丸后能够完成task的工人中力量最小的工人完成task
- 如果此时力量最大的工人无法完成task,且没有药丸,则说明无法安排k个工人完成k个任务
代码
class Solution {
public int maxTaskAssign(int[] tasks, int[] workers, int pills, int strength) {
Arrays.sort(tasks);
Arrays.sort(workers);
int min = 0;
int max = Math.min(tasks.length, workers.length);
while (min < max) {
int mid = (min + max + 1) >> 1;
boolean b = midTaskAssign(tasks, workers, pills, strength, mid);
if (b) {
min = mid;
} else {
max = mid - 1;
}
}
return min;
}
public boolean midTaskAssign(int[] tasks, int[] workers, int pills, int strength, int mid) {
Deque<Integer> dq = new ArrayDeque<>();
int idx = workers.length - 1;
for (int i = mid - 1; i >= 0; i--) {
int task = tasks[i];
while (idx >= 0 && workers[idx] + strength >= task) {
dq.offerFirst(workers[idx]);
idx--;
}
if (dq.isEmpty()) {
return false;
}
if (dq.peekLast() >= task) {
dq.pollLast();
} else if (pills == 0) {
return false;
} else {
dq.pollFirst();
pills--;
}
}
return true;
}
}
关键点
- 二分查找的思想
- 贪心算法的思想
- 怎么找到加上药丸后能够完成task的工人中力量最小的工人