LeetCode #857 Hard

Minimum Cost to Hire K Workers

Minimum Cost to Hire K Workers: hire exactly k workers paid in proportion to their quality, where every worker must earn at least their minimum wage. Return the least total cost.

Constraints
  • n == quality.length == wage.length
  • 1 <= k <= n <= 10⁴
  • 1 <= quality[i], wage[i] <= 10⁴
  • Answers within 10⁻⁵ of the actual answer are accepted
arraygreedysortingheap
Open on LeetCode ↗
Minimum Cost to Hire K Workers diagramA labelled diagram of the structure this problem turns on.cost = rate × total quality — two factors, optimised separatelysorted by wage ÷ quality — ratio rises downwardq20 w50ratio 2.50q5 w30ratio 6.00q10 w70ratio 7.00rate R = the group's largest ratioso R is pinned by the current worker,leaving only Σ quality to minimisefixing one worker as the most expensive makes every cheaper-ratio worker eligible
02

Intuition

Within a paid group everyone shares one wage-per-quality ratio, and that ratio must satisfy the greediest member — so it is the maximum ratio in the group. Sorting workers by ratio means that fixing a worker as the group's most expensive lets every cheaper-ratio worker be a candidate, and the cost is then that ratio times the total quality. Minimising cost therefore means minimising total quality among the k cheapest-quality candidates, which a max-heap maintains as the ratio rises.

How to spot this pattern

When a cost factorises into one value set by the group's extreme member and another that is a sum over the group, sort by the extreme and use a heap for the sum. The pattern — sort to fix one dimension, heap to optimise the other — also drives IPO and Maximum Performance of a Team.

03

Approach

Try it first

Before reading on: derive the single rate that satisfies every worker in a group, and write the total cost as a product of two factors. Then work out why sorting by ratio lets you fix one factor and optimise the other independently.

1

Deriving the payment rule

The two conditions — pay in proportion to quality, and pay each worker at least their minimum wage — combine into a single number per group. If the group is paid at rate R per unit of quality, worker i receives R × quality[i], and this must be at least wage[i], so R >= wage[i] / quality[i]. To satisfy every member at once, R must be the maximum of those ratios. The total cost is then R × Σ quality, which is the product of exactly two quantities — and that factorisation is what makes the problem tractable.

2

Sorting by ratio to fix one factor at a time

Sort workers by wage / quality ascending and sweep. When worker i is processed, treat their ratio as the group's rate R; every worker seen so far has a ratio no larger, so any of them may join without raising R. This turns a two-variable optimisation into a sequence of one-variable ones: with R pinned by the current worker, the only remaining freedom is which k workers to take, and the cost depends on them solely through their total quality.

3

A max-heap to keep total quality minimal

Maintain a max-heap of the qualities of the chosen candidates along with their running sum. Push each worker's quality; once the heap holds more than k, pop the largest, since dropping the highest quality reduces the sum by the most. When the heap holds exactly k, the group is the k smallest-quality workers among those with ratio at most the current one, and the candidate cost is ratio × sum. Take the minimum across the sweep. Sorting costs O(n log n) and each worker enters and leaves the heap once, so the total remains O(n log n) with O(k) space.

04

Solution & live demo

1import heapq
2 
3 
4class Solution:
5 def mincostToHireWorkers(self, quality, wage, k):
6 workers = sorted(
7 (w / q, q) for q, w in zip(quality, wage)
8 )
9 heap = []
10 total_quality = 0
11 best = float("inf")
12 for ratio, q in workers:
13 heapq.heappush(heap, -q)
14 total_quality += q
15 if len(heap) > k:
16 total_quality += heapq.heappop(heap)
17 if len(heap) == k:
18 best = min(best, ratio * total_quality)
19 return best
05

Common pitfalls

Picking the k smallest qualities outright

✗ Wrong
sort by quality, take the k smallest
✓ Right
sort by ratio, then heap the qualities

Total cost is ratio times total quality, and a low-quality worker can carry a very high ratio that inflates the rate for everyone. Optimising one factor alone ignores the product.

Using a min-heap for the qualities

✗ Wrong
heapq.heappush(heap, q)
heapq.heappop(heap)
✓ Right
heapq.heappush(heap, -q)
heapq.heappop(heap)

Evicting must remove the largest quality to keep the sum minimal. A min-heap pops the smallest, discarding the cheapest worker and driving the total up instead of down.

Computing cost before the group is full

✗ Wrong
best = min(best, ratio * total_quality)
✓ Right
if len(heap) == k:
    best = min(best, ratio * total_quality)

With fewer than k workers the sum is smaller and produces a cost that no legal hire can achieve, so the reported minimum is below the true answer.

06

Edge cases

k equals the number of workers

Everyone is hired, and the rate is the largest ratio overall.

k = 1

The answer is simply the smallest wage, since each worker alone costs their own minimum.

Workers with identical ratios

Either may set the rate; the heap still selects the smaller qualities.

One worker with very high quality

They are popped from the heap as soon as the group exceeds k.

Floating-point comparison

Answers within 10⁻⁵ are accepted, so doubles are sufficient.

07

Complexity

Time
O(n log n)
Space
O(k)
Sorting dominates. Each worker is pushed and popped at most once, and the heap never exceeds k entries.