1
+ import java .util .ArrayDeque ;
1
2
import java .util .Arrays ;
2
- import java .util .Map ;
3
- import java .util .TreeMap ;
3
+ import java .util .Deque ;
4
4
5
5
public class Solution2071 {
6
6
public int maxTaskAssign (int [] tasks , int [] workers , int pills , int strength ) {
7
7
Arrays .sort (tasks );
8
- TreeMap <Integer , Integer > treeMap = new TreeMap <>();
9
- for (int worker : workers ) {
10
- treeMap .put (worker , treeMap .getOrDefault (worker , 0 ) + 1 );
11
- }
8
+ Arrays .sort (workers );
9
+ int mn = Math .min (tasks .length , workers .length );
12
10
13
- // 注意边界: 任务能全部被完成
14
- if (checkMid (tasks , new TreeMap <>(treeMap ), pills , strength , tasks .length )) {
15
- return tasks .length ;
16
- }
17
11
// 二分查找
18
12
int left = 1 ;
19
- int right = tasks . length ;
13
+ int right = mn + 1 ;
20
14
while (left < right ) {
21
15
int mid = left + (right - left ) / 2 ;
22
16
// 边界二分 F, F,..., F, [T, T,..., T]
23
17
// ----------------------^
24
- if (!checkMid (tasks , new TreeMap <>( treeMap ) , pills , strength , mid )) {
18
+ if (!checkMid (tasks , workers , pills , strength , new ArrayDeque <>() , mid )) {
25
19
right = mid ;
26
20
} else {
27
21
left = mid + 1 ;
@@ -30,34 +24,33 @@ public int maxTaskAssign(int[] tasks, int[] workers, int pills, int strength) {
30
24
return left - 1 ;
31
25
}
32
26
33
- // 能否完成 mid 个任务
34
- private boolean checkMid (int [] tasks , TreeMap <Integer , Integer > workerMap , int pills , int strength , int mid ) {
35
- for (int i = mid - 1 ; i >= 0 ; i --) {
36
- Map .Entry <Integer , Integer > ceilingEntry = workerMap .ceilingEntry (tasks [i ]);
37
- if (ceilingEntry != null ) {
38
- // 不使用药丸
39
- if (ceilingEntry .getValue () > 1 ) {
40
- workerMap .put (ceilingEntry .getKey (), ceilingEntry .getValue () - 1 );
41
- } else {
42
- workerMap .remove (ceilingEntry .getKey ());
43
- }
44
- } else {
45
- // 使用药丸
46
- if (pills == 0 ) {
47
- return false ;
48
- }
49
- pills --;
50
- Map .Entry <Integer , Integer > entry = workerMap .ceilingEntry (tasks [i ] - strength );
51
- if (entry != null ) {
52
- if (entry .getValue () > 1 ) {
53
- workerMap .put (entry .getKey (), entry .getValue () - 1 );
54
- } else {
55
- workerMap .remove (entry .getKey ());
56
- }
57
- } else {
58
- return false ;
59
- }
27
+ // 添加(能完成的)任务:往队尾插入数据。
28
+ // 删除最简单的任务:去掉队首。
29
+ // 删除(能完成的)最难的任务:去掉队尾。
30
+ private boolean checkMid (int [] tasks , int [] workers , int pills , int strength , Deque <Integer > dq , int k ) {
31
+ // 贪心:用最强的 k 名工人,完成最简单的 k 个任务
32
+ int i = 0 ;
33
+ for (int j = workers .length - k ; j < workers .length ; j ++) { // 枚举工人
34
+ int w = workers [j ];
35
+ // 在吃药的情况下,把能完成的任务记录到 buf 中
36
+ while (i < k && tasks [i ] <= w + strength ) {
37
+ dq .addLast (tasks [i ]);
38
+ i ++;
39
+ }
40
+ // 即使吃药也无法完成任务
41
+ if (dq .isEmpty ()) return false ;
42
+ // 无需吃药就能完成(最简单的)任务
43
+ if (w >= dq .getFirst ()) {
44
+ dq .removeFirst ();
45
+ continue ;
46
+ }
47
+ // 必须吃药
48
+ if (pills == 0 ) { // 没药了
49
+ return false ;
60
50
}
51
+ pills --;
52
+ // 完成(能完成的)最难的任务
53
+ dq .removeLast ();
61
54
}
62
55
return true ;
63
56
}
0 commit comments