Problem: 2071. 你可以安排的最多任务数目
思路
这是一个二分查找和贪心算法的结合问题。我们需要找出可以完成的最大任务数量,这个数量是在任务和工人之间的一个平衡。我们可以使用二分查找来确定这个平衡点,然后使用贪心算法来尽可能地完成更多的任务。
解题方法
我们首先对任务和工人的能力进行排序,然后使用二分查找来确定可以完成的最大任务数量。在每一次二分查找的过程中,我们都会尝试使用当前的中间值作为可能的最大任务数量,然后使用贪心算法来判断是否可以完成这么多的任务。
在贪心算法中,我们会尽可能地让工人在不使用药物的情况下完成任务。如果工人的能力不足以完成任务,我们就会考虑使用药物。我们会优先让能力较弱的工人使用药物,因为他们使用药物后能够带来的能力提升更大。
复杂度
时间复杂度:
O ( n log n ) O(n \log n) O(nlogn),其中 n n n 是任务的数量。我们需要对任务和工人的能力进行排序,然后进行二分查找。
空间复杂度:
O ( n ) O(n) O(n),我们需要使用额外的空间来存储任务和工人的能力。
Code
class Solution {
static int MAXN = 50001;
static int[] deque = new int[MAXN];
static int h, t;
static int[] tasks;
static int[] works;
public int maxTaskAssign(int[] ts, int[] ws, int pills, int strength) {
tasks = ts;
works = ws;
Arrays.sort(works);
Arrays.sort(tasks);
int wsize = works.length;
int tsize = tasks.length;
int ans = 0, l = 0, r = Math.min(tsize, wsize);
while (l <= r) {
int m = (l + r) >> 1;
if (f(0, m - 1, wsize - m, wsize - 1, strength, pills)) {
ans = m;
l = m + 1;
} else {
r = m - 1;
}
}
return ans;
}
private static boolean f(int tl, int tr, int wl, int wr, int strength, int pills) {
h = t = 0;
int cnts = 0; // 已经使用药的数量
for (int i = wl, j = tl; i <= wr; i++) {
// 工人不吃药的情况 去解锁任务
for (; j <= tr && tasks[j] <= works[i]; j++) {
deque[t++] = j;
}
if (h < t && tasks[deque[h]] <= works[i]) {
h++;
} else {
// 吃药逻辑
for (; j <= tr && tasks[j] <= works[i] + strength; j++) {
deque[t++] = j;
}
if (h < t) {
cnts++;
t--;
} else {
return false;
}
}
}
return cnts <= pills;
}
}