Maximum Number of Tasks You Can Assign - Complete Solution Guide
Maximum Number of Tasks You Can Assign is LeetCode problem 2071, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
You have n tasks and m workers. Each task has a strength requirement stored in a 0-indexed integer array tasks , with the i th task requiring tasks[i] strength to complete. The strength of each worker is stored in a 0-indexed integer array workers , with the j th worker having workers[j] strength. Each worker can only be assigned to a single task and must have a strength greater than or equal to the task's strength requirement (i.e., workers[j] >= tasks[i] ). Additionally, you have pills magical
Detailed Explanation
The problem asks us to find the maximum number of tasks that can be completed given a set of tasks with strength requirements, a set of workers with strength, a number of pills, and the strength increase each pill provides. Each worker can only be assigned to one task, and their strength must be greater than or equal to the task's strength requirement. Pills can be given to workers to increase their strength, but each worker can receive at most one pill. The goal is to maximize the number of assigned tasks.
Solution Approach
The solution uses a binary search approach to find the maximum number of tasks that can be completed. For each possible number of tasks (the 'mid' value in the binary search), a helper function `can_assign` checks if it's possible to assign that many tasks. The `can_assign` function sorts the first k tasks (easiest k tasks) and workers, then iterates through the tasks in reverse order of strength requirement. For each task, it checks if there are workers strong enough to complete it. If not, it attempts to use a pill on a worker. If no worker can complete the task even with a pill, the function returns `false`. The binary search adjusts the search space based on the result of `can_assign` to find the optimal number of tasks.
Step-by-Step Algorithm
- Step 1: Sort the `tasks` and `workers` arrays in ascending order.
- Step 2: Perform a binary search on the possible number of tasks, from 0 to the minimum of the lengths of `tasks` and `workers`.
- Step 3: Inside the binary search, define a helper function `can_assign(k)` that takes an integer `k` as input, representing the number of tasks we want to try to assign.
- Step 4: In `can_assign(k)`, initialize `pills_remaining` to the initial number of `pills`. Also, initialize a deque `overqualified_workers` to store workers that are strong enough to complete the task without a pill. Initialize the `worker_ptr` pointing to the strongest worker (m-1).
- Step 5: Iterate through the `k` easiest tasks in reverse order of difficulty (from hardest to easiest).
- Step 6: For each task, find all workers strong enough without a pill (add them to the `overqualified_workers` deque from strongest to weakest).
- Step 7: If there are overqualified workers for a given task, assign the weakest available worker (pop from the end of the deque).
- Step 8: If no overqualified worker available, check if we can use a pill to make an underqualified worker strong enough for the task. Pick the strongest underqualified worker (workers[worker_ptr]), and if even with a pill that worker can't complete the task, then assigning this many tasks (k) is impossible, return `false`.
- Step 9: If there are no overqualified workers and no pills available, then assigning this many tasks (k) is impossible, return `false`.
- Step 10: If `can_assign(k)` returns `true`, it means we can assign at least `k` tasks, so update the `ans` and search for a larger number of tasks (update `low` to `mid + 1`).
- Step 11: If `can_assign(k)` returns `false`, it means we cannot assign `k` tasks, so search for a smaller number of tasks (update `high` to `mid - 1`).
- Step 12: After the binary search completes, return the maximum number of tasks `ans` that could be assigned.
Key Insights
- Insight 1: Sorting both tasks and workers allows us to efficiently use a greedy approach within a binary search framework.
- Insight 2: Binary search is applicable because the problem asks for the *maximum* number of tasks. We can check if a given number of tasks is possible to complete, allowing binary search on the possible number of tasks.
- Insight 3: Using a deque to maintain workers who are already strong enough for a task allows us to prioritize using those workers before resorting to pills. This helps conserve pills for later, harder tasks.
Complexity Analysis
Time Complexity: O(n*log(n)*log(min(n,m)))
Space Complexity: O(1)
Topics
This problem involves: Array, Two Pointers, Binary Search, Greedy, Queue, Sorting, Monotonic Queue.
Companies
Asked at: Coupang, IBM, Walmart Labs.