Skip to content

Commit a287c07

Browse files
committed
feat: 2071
1 parent 2051d73 commit a287c07

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,81 @@
11
# 2071. Maximum Number of Tasks You Can Assign
2+
3+
## Intuition
4+
5+
The problem asks us to find the maximum number of tasks we can assign to workers, where each worker can complete at most one task. Workers have different strengths, tasks have different requirements, and we have a limited number of pills that can boost a worker's strength by a fixed amount.
6+
7+
The key insight is that this is an optimization problem where we want to maximize the number of completed tasks. We can use binary search on the answer - if we can complete k tasks, we might be able to complete k+1 tasks, but if we can't complete k tasks, we definitely can't complete more than k tasks.
8+
9+
## Approach
10+
11+
1. **Sort both arrays**: Sort tasks in ascending order and workers in descending order of their strength.
12+
2. **Binary search on the answer**: Use binary search to find the maximum number of tasks we can complete. The search space is from 0 to min(len(tasks), len(workers)).
13+
3. **Greedy assignment strategy**: For a given number k of tasks to complete:
14+
- Take the k easiest tasks (first k tasks after sorting)
15+
- Take the k strongest workers (last k workers after sorting)
16+
- Process tasks from hardest to easiest among the selected k tasks
17+
- For each task, try to assign it using the greedy strategy:
18+
- First, try to assign the strongest available worker without using a pill
19+
- If that's not possible, find the weakest worker who can complete the task with a pill
20+
- If no worker can complete the task even with a pill, return false
21+
4. **Optimization with pills**: When we need to use a pill, we should use it on the weakest possible worker who can complete the task. This preserves stronger workers for harder tasks.
22+
23+
The greedy strategy works because:
24+
25+
- We process harder tasks first, ensuring they get priority for stronger workers
26+
- When using pills, we use them on the weakest capable worker to preserve stronger workers
27+
- This maximizes our chances of completing all k tasks
28+
29+
## Complexity
30+
31+
- Time complexity: O(n log n + m log m + log(min(n,m)) × m log m)
32+
- Space complexity: O(m)
33+
34+
## Keywords
35+
36+
- Binary Search
37+
- Greedy Algorithm
38+
39+
## Code
40+
41+
```go
42+
func maxTaskAssign(tasks []int, workers []int, pills int, strength int) int {
43+
sort.Ints(tasks)
44+
sort.Ints(workers)
45+
46+
canAssign := func(k int) bool {
47+
avail, remain := append(make([]int, 0), workers[len(workers) - k:]...), pills
48+
for i := k - 1; i >= 0; i -= 1 {
49+
require := tasks[i]
50+
if len(avail) > 0 && avail[len(avail) - 1] >= require {
51+
avail = avail[: len(avail) - 1]
52+
} else {
53+
if remain <= 0 {
54+
return false
55+
}
56+
thresold := require - strength
57+
idx := sort.Search(len(avail), func(j int) bool {
58+
return avail[j] >= thresold
59+
})
60+
if idx == len(avail) {
61+
return false
62+
}
63+
avail = append(avail[:idx], avail[idx + 1:]...)
64+
remain -= 1
65+
}
66+
}
67+
return true
68+
}
69+
70+
left, right, complete := 0, min(len(tasks), len(workers)), 0
71+
for left <= right {
72+
mid := (left + right) / 2
73+
if canAssign(mid) {
74+
complete, left = mid, mid + 1
75+
} else {
76+
right = mid - 1
77+
}
78+
}
79+
return complete
80+
}
81+
```

Week14/2071 AC.png

42.1 KB
Loading
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# 2071. Maximum Number of Tasks You Can Assign
2+
3+
## Intuition
4+
5+
The problem asks us to find the maximum number of tasks we can assign to workers, where each worker can complete at most one task. Workers have different strengths, tasks have different requirements, and we have a limited number of pills that can boost a worker's strength by a fixed amount.
6+
7+
The key insight is that this is an optimization problem where we want to maximize the number of completed tasks. We can use binary search on the answer - if we can complete k tasks, we might be able to complete k+1 tasks, but if we can't complete k tasks, we definitely can't complete more than k tasks.
8+
9+
## Approach
10+
11+
1. **Sort both arrays**: Sort tasks in ascending order and workers in descending order of their strength.
12+
2. **Binary search on the answer**: Use binary search to find the maximum number of tasks we can complete. The search space is from 0 to min(len(tasks), len(workers)).
13+
3. **Greedy assignment strategy**: For a given number k of tasks to complete:
14+
- Take the k easiest tasks (first k tasks after sorting)
15+
- Take the k strongest workers (last k workers after sorting)
16+
- Process tasks from hardest to easiest among the selected k tasks
17+
- For each task, try to assign it using the greedy strategy:
18+
- First, try to assign the strongest available worker without using a pill
19+
- If that's not possible, find the weakest worker who can complete the task with a pill
20+
- If no worker can complete the task even with a pill, return false
21+
4. **Optimization with pills**: When we need to use a pill, we should use it on the weakest possible worker who can complete the task. This preserves stronger workers for harder tasks.
22+
23+
The greedy strategy works because:
24+
25+
- We process harder tasks first, ensuring they get priority for stronger workers
26+
- When using pills, we use them on the weakest capable worker to preserve stronger workers
27+
- This maximizes our chances of completing all k tasks
28+
29+
## Complexity
30+
31+
- Time complexity: O(n log n + m log m + log(min(n,m)) × m log m)
32+
- Space complexity: O(m)
33+
34+
## Keywords
35+
36+
- Binary Search
37+
- Greedy Algorithm
38+
39+
## Code
40+
41+
```go
42+
func maxTaskAssign(tasks []int, workers []int, pills int, strength int) int {
43+
sort.Ints(tasks)
44+
sort.Ints(workers)
45+
46+
canAssign := func(k int) bool {
47+
avail, remain := append(make([]int, 0), workers[len(workers) - k:]...), pills
48+
for i := k - 1; i >= 0; i -= 1 {
49+
require := tasks[i]
50+
if len(avail) > 0 && avail[len(avail) - 1] >= require {
51+
avail = avail[: len(avail) - 1]
52+
} else {
53+
if remain <= 0 {
54+
return false
55+
}
56+
thresold := require - strength
57+
idx := sort.Search(len(avail), func(j int) bool {
58+
return avail[j] >= thresold
59+
})
60+
if idx == len(avail) {
61+
return false
62+
}
63+
avail = append(avail[:idx], avail[idx + 1:]...)
64+
remain -= 1
65+
}
66+
}
67+
return true
68+
}
69+
70+
left, right, complete := 0, min(len(tasks), len(workers)), 0
71+
for left <= right {
72+
mid := (left + right) / 2
73+
if canAssign(mid) {
74+
complete, left = mid, mid + 1
75+
} else {
76+
right = mid - 1
77+
}
78+
}
79+
return complete
80+
}
81+
```

0 commit comments

Comments
 (0)