Fairly Distribute Money With Limits
Company: Gusto
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
# Fairly Distribute Money With Limits
You are given an integer `amount` representing a total sum of money to distribute, and a list of `employees`. Each employee is described by:
- `name` — a unique string identifier.
- `limit` — a non-negative integer giving the maximum amount that person is allowed to receive.
Distribute the entire `amount` (when possible) among the employees subject to these rules:
1. **Cap rule.** No employee may receive more than their `limit`.
2. **Even distribution.** The money is shared as evenly as possible among the employees who have not yet reached their cap.
3. **Redistribution.** When an employee hits their `limit`, any money they cannot accept is redistributed among the remaining employees who still have room — again, as evenly as possible.
Return a mapping from each employee `name` to the integer amount they receive.
## Distribution semantics
Because the amount is an integer and must be split as evenly as possible, distribute in **whole units** so that the result is deterministic:
- At each step, consider only employees whose current allocation is still below their `limit` (the "active" set).
- Give each active employee an equal whole-unit share of the remaining money. If the remaining money does not divide evenly across the active set, the leftover indivisible units (`remaining % active_count` of them) are handed out one extra unit at a time to the active employees **in ascending order of `name`** (lexicographic), so that the tie-break is fully specified.
- Whenever an employee reaches their `limit`, they leave the active set and their unused share returns to the pool to be redistributed in the next step.
- Stop when either all money is distributed or every employee has reached their `limit`.
If the total of all limits is less than `amount`, every employee receives exactly their `limit` and `amount - sum(limits)` units remain undistributed (they are simply not assigned to anyone).
## Input / Output
- `amount`: integer, `0 <= amount <= 10^9`.
- `employees`: a list of `(name, limit)` pairs. Names are unique. `0 <= limit <= 10^9`. The list has between `1` and `10^5` employees.
Return a dictionary (map) from `name` to the integer amount that name receives. Every employee name in the input must appear in the output, including those who receive `0`.
## Examples
**Example 1**
```
amount = 100
employees = [("Alice", 50), ("Bob", 50), ("Carol", 50)]
```
Output:
```
{"Alice": 34, "Bob": 33, "Carol": 33}
```
Each person could take up to 50, so no cap binds. 100 split three ways is 33 each with 1 unit left over; the leftover unit goes to the lexicographically smallest name, `Alice`.
**Example 2**
```
amount = 100
employees = [("Alice", 10), ("Bob", 100), ("Carol", 100)]
```
Output:
```
{"Alice": 10, "Bob": 45, "Carol": 45}
```
An even 3-way split would give each about 33, but `Alice` is capped at 10. `Alice` takes 10, then the remaining 90 is split evenly between `Bob` and `Carol`, giving 45 each.
**Example 3**
```
amount = 5
employees = [("Alice", 1), ("Bob", 1)]
```
Output:
```
{"Alice": 1, "Bob": 1}
```
Total limits sum to 2, which is less than 5. Each gets their cap of 1, and 3 units remain undistributed.
Quick Answer: This question tests practical algorithm design around greedy distribution with per-element constraints and iterative redistribution. It evaluates a candidate's ability to handle integer division edge cases, tie-breaking rules, and simulation-style problems commonly found in coding interviews for software engineering roles.
You are given an integer `amount` (the total money to distribute) and a list of `employees`, each a `(name, limit)` pair where `name` is a unique string and `limit` is the maximum that person may receive. Distribute the money in whole units, as evenly as possible, subject to a per-person cap.
**Rules**
1. **Cap.** No employee may receive more than their `limit`.
2. **Even split.** At each step, give every *active* employee (one whose current allocation is still below their `limit`) an equal whole-unit share of the money that still remains.
3. **Deterministic remainder.** If the remaining money does not divide evenly across the active set, the `remaining % active_count` leftover indivisible units are handed out one extra unit at a time to active employees in **ascending lexicographic order of `name`**.
4. **Redistribution.** Whenever an employee reaches their `limit`, they leave the active set and any money they could not accept returns to the pool to be redistributed in the next step.
5. **Stop** when either all the money is distributed or every employee has reached their `limit`. If `sum(limits) < amount`, everyone gets exactly their `limit` and `amount - sum(limits)` units are left undistributed (assigned to no one).
Return a mapping from each `name` to the integer amount they receive. Every input name must appear in the output, including those receiving `0`.
**Constraints**
- `0 <= amount <= 10^9`
- `1 <= len(employees) <= 10^5`, names unique
- `0 <= limit <= 10^9`
**Example 1** — `amount = 100`, `employees = [("Alice",50),("Bob",50),("Carol",50)]` → `{"Alice":34,"Bob":33,"Carol":33}` (no cap binds; 100/3 = 33 each, the 1 leftover unit goes to the lexicographically smallest name `Alice`).
**Example 2** — `amount = 100`, `employees = [("Alice",10),("Bob",100),("Carol",100)]` → `{"Alice":10,"Bob":45,"Carol":45}` (Alice caps at 10; the remaining 90 splits evenly between Bob and Carol).
**Example 3** — `amount = 5`, `employees = [("Alice",1),("Bob",1)]` → `{"Alice":1,"Bob":1}` (total limits = 2 < 5; each gets their cap of 1 and 3 units remain undistributed).
Constraints
- 0 <= amount <= 10^9
- 1 <= number of employees <= 10^5
- 0 <= limit <= 10^9
- All names are unique strings.
- Allocations and all intermediate sums fit in 64-bit integers.
Examples
Input: (100, [("Alice", 50), ("Bob", 50), ("Carol", 50)])
Expected Output: {"Alice": 34, "Bob": 33, "Carol": 33}
Explanation: No cap binds. 100 // 3 = 33 each, with 1 leftover unit going to the lexicographically smallest name, Alice.
Input: (100, [("Alice", 10), ("Bob", 100), ("Carol", 100)])
Expected Output: {"Alice": 10, "Bob": 45, "Carol": 45}
Explanation: Alice caps at 10; the remaining 90 is split evenly between Bob and Carol, 45 each.
Input: (5, [("Alice", 1), ("Bob", 1)])
Expected Output: {"Alice": 1, "Bob": 1}
Explanation: sum(limits) = 2 < 5. Each gets their cap of 1 and 3 units remain undistributed.
Input: (0, [("Solo", 1000)])
Expected Output: {"Solo": 0}
Explanation: Edge case: nothing to distribute, so the only employee receives 0 but still appears in the output.
Input: (7, [("Alice", 2), ("Bob", 2), ("Carol", 2)])
Expected Output: {"Alice": 2, "Bob": 2, "Carol": 2}
Explanation: Total limits = 6 < 7; everyone caps at 2 and the remaining 1 unit is left undistributed.
Input: (10, [("Bob", 3), ("Alice", 100), ("Carol", 100)])
Expected Output: {"Bob": 3, "Alice": 4, "Carol": 3}
Explanation: First round of 10/3 = 3 each caps Bob at 3; the 1 leftover unit goes to lex-smallest Alice. The 1 unit Bob couldn't take... here Bob exactly hits 3, so remaining 7 over Alice+Carol gives 4 (lex-smallest Alice) and 3.
Input: (1, [("Zed", 5), ("Amy", 5)])
Expected Output: {"Zed": 0, "Amy": 1}
Explanation: A single indivisible unit (share = 0, extra = 1) goes to the lexicographically smallest active name, Amy.
Input: (1000000000, [("X", 1000000000)])
Expected Output: {"X": 1000000000}
Explanation: Boundary: a single employee absorbs the full 10^9 since their limit allows it.
Hints
- Simulate in rounds. In each round, only the 'active' employees (those still below their limit) share the money that remains.
- Split evenly with integer division: each active employee gets floor(remaining / active_count). The leftover remaining % active_count units must go somewhere deterministic.
- Hand the leftover units out one at a time to active employees in ascending lexicographic order of name — pre-sorting the indices by name once makes this clean.
- When an employee's share would exceed their remaining room, give them only their room; the unused part stays in the pool and is redistributed next round. Stop when nothing remains or no one is active.