|
| 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