Distribute Money to Maximum Children
EasyPrompt
You are given an integer money denoting the amount of money (in dollars) that you have and another integer children denoting the number of children that you must distribute the money to.
You have to distribute the money according to the following rules:
- All money must be distributed.
- Everyone must receive at least
1dollar. - Nobody receives
4dollars.
Return the maximum number of children who may receive exactly 8 dollars if you distribute the money according to the aforementioned rules. If there is no way to distribute the money, return -1.
Example 1:
Input: money = 20, children = 3
Output: 1
Explanation:
The maximum number of children with 8 dollars will be 1. One of the ways to distribute the money is:
- 8 dollars to the first child.
- 9 dollars to the second child.
- 3 dollars to the third child.
It can be proven that no distribution exists such that number of children getting 8 dollars is greater than 1.Example 2:
Input: money = 16, children = 2
Output: 2
Explanation: Each child can be given 8 dollars.
Constraints:
1 <= money <= 2002 <= children <= 30
Approaches
2 approaches with complexity analysis and trade-offs.
This approach systematically checks every possible number of children that can receive $8, starting from the highest possible number (children) down to zero. For each potential count, it verifies if the remaining money can be distributed to the remaining children while adhering to all the given rules. The first count that allows for a valid distribution is guaranteed to be the maximum, so we can return it immediately. This method is essentially a linear search for the answer.
Algorithm
- If
money < children, it's impossible to give each child at least $1. Return -1. - Iterate through the number of children who could receive $8, let's call it
k, from the maximum possible (children) down to0. - For each
k, calculate the money that would be spent (k * 8) and the remaining money (rem_money) and remaining children (rem_children). - If the money spent exceeds the total
money, thiskis not feasible, so we continue tok-1. - Check if the
rem_moneycan be validly distributed amongrem_children:- If
rem_childrenis 0,rem_moneymust also be 0. If so, we found a valid distribution forkchildren, and since we iterate downwards, this is the maximum. Returnk. - If
rem_childrenis greater than 0, we must ensure two conditions: (a) each remaining child can get at least $1 (rem_money >= rem_children), and (b) we don't run into the special case where we are forced to give the last child $4 (this happens only whenrem_children == 1andrem_money == 4).
- If
- If both conditions in step 5 are met,
kis a valid answer. Returnk. - If the loop completes, it implies no solution was found, which should only happen if the initial check
money < childrenwas true. A fallback return of -1 handles this.
Walkthrough
The core idea is to iterate and check. We want to maximize the number of children, k, who get $8. We can simply try all possible values for k and see which ones are valid.
To be efficient, we should start our search from the highest possible value of k, which is children, and go down to 0. The first value of k that allows a valid distribution of the entire money will be our answer.
For a given k, we check its validity as follows:
- Calculate the money given to these
kchildren:spent = k * 8. Ifspent > money, thiskis impossible. - Calculate the remaining money
rem_money = money - spentand remaining childrenrem_children = children - k. - Now, we must distribute
rem_moneyamongrem_children.- If
rem_children == 0, all children were given $8. This is only valid ifrem_money == 0. - If
rem_children > 0, every one of them must get at least $1, sorem_money >= rem_children. Additionally, we must not be forced to give a child exactly $4. This problematic scenario only occurs when there is exactly one child left (rem_children == 1) and the exact amount of money left is $4 (rem_money == 4).
- If
If a value of k passes these checks, it's a valid solution. Since we are iterating downwards, the first one we find is the maximum.
class Solution { public int distMoney(int money, int children) { if (money < children) { return -1; } // Iterate from the maximum possible children getting $8 downwards. for (int k = children; k >= 0; k--) { int spent_money = k * 8; if (spent_money > money) { continue; } int rem_money = money - spent_money; int rem_children = children - k; if (rem_children == 0) { if (rem_money == 0) { return k; // Perfect distribution } } else { // Check if remaining money can be distributed if (rem_money >= rem_children) { // Check for the forbidden $4 case if (rem_children == 1 && rem_money == 4) { continue; // This k is invalid } return k; // Found a valid distribution } } } return -1; // Should not be reached if money >= children }}Complexity
Time
O(children) because, in the worst case, the loop runs from `children` down to 0.
Space
O(1) as it only uses a few variables for calculations, regardless of the input size.
Trade-offs
Pros
The logic is straightforward and easy to follow.
It correctly handles all edge cases by its nature of checking every possibility.
Cons
Slightly less efficient than a direct mathematical solution.
For very large constraints on
children, this approach could be too slow, but it's perfectly fine for the given constraints.
A more optimal solution can be achieved by using mathematical reasoning to directly calculate the result in constant time. This approach avoids any iteration by breaking the problem down into a set of distinct cases based on the relationship between the amount of money and the number of children. By analyzing the constraints, we can derive a formula to find the answer.
Algorithm
- Handle the base case: if
money < children, return -1. - Conceptually, give every child $1 first to satisfy a core rule. The remaining money is
money - children. - The problem now is to distribute this remaining amount to the
children, where each needs an additional $7 to reach a total of $8. - Calculate the maximum number of children who can receive an additional $7:
count = (money - children) / 7. - Calculate the leftover money after this distribution:
remainder = (money - children) % 7. - Analyze the results based on a few distinct cases:
- If
countis greater thanchildren, it means we have more than enough money to give everyone $8. We can't give everyone $8 because money would be left over. The answer ischildren - 1. - If
countequalschildren, we can give everyone $8 if and only if theremainderis 0. If there is a remainder, one child must take it, so onlychildren - 1children get exactly $8. - If
countis less thanchildren,countis our candidate answer. However, we must check the$4rule. This rule is violated if we are left with one child (children - count == 1) who has $1, and theremainderto be given is $3 (totaling $4). In this specific scenario, the answer iscount - 1. Otherwise, the answer iscount.
- If
Walkthrough
This approach solves the problem without any loops by performing a case analysis.
First, we handle the trivial invalid case: if money < children, it's impossible, so we return -1.
To simplify the problem, we can first satisfy the rule that everyone gets at least $1. We distribute $1 to each of the children, which uses up children dollars. The remaining money is money - children. Now, our goal is to distribute this remaining money to give as many children as possible an additional $7 to make their total $8.
The number of children we can give an additional $7 to is count = (money - children) / 7. The money left after this is remainder = (money - children) % 7.
We can now determine the final answer with a few checks:
-
Too much money (
count > children): This happens ifmoneywas initially much larger than8 * children. We can't give everyone $8 because money would be left over. The best we can do is givechildren - 1kids $8 and the last kid all the rest. The answer ischildren - 1. -
Just enough money (
count == children): We have enough to give everyone an additional $7. Ifremainder == 0, everyone gets exactly $8. The answer ischildren. Ifremainder > 0, the extra money must go to one child, meaning onlychildren - 1children end up with exactly $8. -
Not enough money (
count < children): We can givecountchildren $8. Theremaindermust be distributed among thechildren - countkids who still have only $1. The only problem arises if there's exactly one child left (children - count == 1) and theremainderis exactly 3, as this child would receive a total of$1 + $3 = $4. In this specific scenario, we must break up one of the $8 packages, reducing the number of children with $8 by one. So the answer iscount - 1. In all other sub-cases,countis the correct answer.
class Solution { public int distMoney(int money, int children) { // 1. Not enough money to give every child $1. if (money < children) { return -1; } // 2. Special case: too much money. We can't give everyone $8. // The max is children - 1. The last child gets the large remainder. if (money > 8 * children) { return children - 1; } // 3. Special case: giving k = children - 1 leaves the last child with $4. // This happens when money = 8 * (children - 1) + 4, which is 8 * children - 4. // In this case, the answer must be k = children - 2. if (money == 8 * children - 4) { return children - 2; } // 4. General case: The number of children getting $8 is limited by the need // to give the rest at least $1. money - 8k >= children - k => k <= (money - children) / 7. return (money - children) / 7; }}Complexity
Time
O(1) because it involves a fixed number of arithmetic operations and comparisons.
Space
O(1) as no extra space proportional to the input size is required.
Trade-offs
Pros
Extremely efficient, with a constant time complexity.
It's the optimal solution in terms of performance.
Cons
The logic is more complex and requires careful mathematical case analysis to derive.
It can be less intuitive to come up with during an interview compared to the iterative approach.
Solutions
Solution
class Solution {public int distMoney(int money, int children) { if (money < children) { return -1; } if (money > 8 * children) { return children - 1; } if (money == 8 * children - 4) { return children - 2; }class Solution {public: int distMoney(int money, int children) { if (money < children) { return -1; } if (money > 8 * children) { return children - 1; } if (money == 8 * children - 4) { return children - 2; }class Solution: # money-8x >= children-x, x <= (money-children)/7 return ( money - children ) // 7 def distMoney(self, money: int, children: int) -> int: if money < children: return - 1 if money > 8 * children: return children - 1 if money == 8 * children - 4: return children - 2Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.