easy Water Bottles
Problem Statement
There are numBottles number of bottles filled with water. You can trade a numExchange number of empty bottles and get a single filled water bottle.
When you drink a bottle, it becomes empty.
Given the two integers numBottles and numExchange, return the maximum number of water bottles you can drink.
Examples
Example 1
- Input: numBottles =
15, numExchange =4 - Expected Output:
19 - Explanation:
- You start with 15 full bottles.
- Drink 15 bottles (now 15 empty).
- Exchange 12 empty bottles for 3 full (now 3 full, 3 empty).
- Drink 3 more (now 6 empty).
- Exchange 4 empty for 1 full (now 1 full, 2 empty).
- Drink 1 more (now 3 empty).
- You can't get 1 full bottle using
3empty bottles. - You can drink 15 + 3 + 1 = 19 bottoles.
Example 2
- Input: numBottles =
7, numExchange =3 - Expected Output:
10 - Explanation:
- Start with 7 full bottles.
- Drink 7 bottles (7 empty).
- Exchange 6 empty for 2 full (now 2 full, 1 empty).
- Drink 2 more (3 empty).
- Exchange 3 empty for 1 full (now 1 full, 0 empty).
- Drink 1 more (total = 7 + 2 + 1 = 10).
Example 3
- Input: numBottles =
5, numExchange =5 - Expected Output:
6 - Explanation:
- Start with 5 full bottles.
- Drink 5 bottles (5 empty).
- Exchange 5 empty for 1 full (now 1 full, 0 empty).
- Drink 1 more (total = 5 + 1 = 6).
Constraints:
- 1 <= numBottles <= 100
- 2 <= numExchange <= 100
Try it yourself
Try solving this question here:
✅ Solution Water Bottles
Problem Statement
There are numBottles number of bottles filled with water. You can trade a numExchange number of empty bottles and get a single filled water bottle.
When you drink a bottle, it becomes empty.
Given the two integers numBottles and numExchange, return the maximum number of water bottles you can drink.
Examples
Example 1
- Input: numBottles =
15, numExchange =4 - Expected Output:
19 - Explanation:
- You start with 15 full bottles.
- Drink 15 bottles (now 15 empty).
- Exchange 12 empty bottles for 3 full (now 3 full, 3 empty).
- Drink 3 more (now 6 empty).
- Exchange 4 empty for 1 full (now 1 full, 2 empty).
- Drink 1 more (now 3 empty).
- You can't get 1 full bottle using
3empty bottles. - You can drink 15 + 3 + 1 = 19 bottoles.
Example 2
- Input: numBottles =
7, numExchange =3 - Expected Output:
10 - Explanation:
- Start with 7 full bottles.
- Drink 7 bottles (7 empty).
- Exchange 6 empty for 2 full (now 2 full, 1 empty).
- Drink 2 more (3 empty).
- Exchange 3 empty for 1 full (now 1 full, 0 empty).
- Drink 1 more (total = 7 + 2 + 1 = 10).
Example 3
- Input: numBottles =
5, numExchange =5 - Expected Output:
6 - Explanation:
- Start with 5 full bottles.
- Drink 5 bottles (5 empty).
- Exchange 5 empty for 1 full (now 1 full, 0 empty).
- Drink 1 more (total = 5 + 1 = 6).
Constraints:
- 1 <= numBottles <= 100
- 2 <= numExchange <= 100
Solution
To solve this problem, we need to maximize the number of water bottles we can drink by making use of the exchange system for empty bottles. We start by drinking numExchange number of water bottles in 1 move and exchange it with 1 full bottle. We continue this process until we no longer have enough empty bottles to exchange for a full one. This approach works because it allows us to maximize the number of full bottles we can drink by continuously converting empty bottles back into full ones as long as possible.
Step-by-step Algorithm
-
Initialize
totalDrunkBottlesto 0:- We start with
totalDrunkBottles = 0to keep a count of all the bottles we drink during the process.
- We start with
-
While loop (
numBottles >= numExchange):- This loop ensures that as long as we have enough bottles to exchange for at least one full bottle, we continue the process.
-
Inside the Loop: Drink and Exchange
- Add
numExchangetototalDrunkBottles:- In each iteration, we drink as many bottles as we can exchange in that round, so we add
numExchangetototalDrunkBottles.
- In each iteration, we drink as many bottles as we can exchange in that round, so we add
- Subtract
numExchangefromnumBottles:- After drinking
numExchangebottles, we subtract this number fromnumBottlesbecause those bottles are now empty.
- After drinking
- Increment
numBottlesby 1:- After subtracting
numExchange, we simulate exchanging the empty bottles to get one full bottle back, thus incrementingnumBottlesby 1.
- After subtracting
- Add
-
Add Remaining Bottles to
totalDrunkBottles:- Once the loop exits (when
numBottles < numExchange), we add any remaining bottles tototalDrunkBottlesbecause these are the bottles we can still drink but cannot exchange for more.
- Once the loop exits (when
-
Return
totalDrunkBottles.
Algorithm Walkthrough
Input: numBottles = 15, numExchange = 4
-
Initialize
totalDrunkBottlesto 0. -
Start with 15 full bottles:
- Iteration 1:
- Drink 4 bottles: totalDrunkBottles = 4, numBottles = 11 (15 - 4)
- Exchange 4 empty bottles for 1 full bottle: numBottles = 12 (11 + 1)
- Iteration 2:
- Drink 4 bottles: totalDrunkBottles = 8, numBottles = 8 (12 - 4)
- Exchange 4 empty bottles for 1 full bottle: numBottles = 9 (8 + 1)
- Iteration 3:
- Drink 4 bottles: totalDrunkBottles = 12, numBottles = 5 (9 - 4)
- Exchange 4 empty bottles for 1 full bottle: numBottles = 6 (5 + 1)
- Iteration 4:
- Drink 4 bottles: totalDrunkBottles = 16, numBottles = 2 (6 - 4)
- Exchange 4 empty bottles for 1 full bottle: numBottles = 3 (2 + 1)
- Iteration 1:
-
Add remaining bottles to totalDrunkBottles: totalDrunkBottles = 19 (16 + 3)
-
Return
totalDrunkBottles: 19
Code
class Solution {
public int getMaxBottles(int numBottles, int numExchange) {
int totalDrunkBottles = 0; // This will keep track of the total number of bottles drunk
while (numBottles >= numExchange) {
// Drink as many bottles as we can exchange in this round
totalDrunkBottles += numExchange;
numBottles -= numExchange;
// Exchange the empty bottles for one full bottle
numBottles++;
}
// Add the remaining bottles that are less than the exchange rate
return totalDrunkBottles + numBottles;
}
public static void main(String[] args) {
Solution solution = new Solution();
// Test cases
System.out.println(solution.getMaxBottles(15, 4)); // Output: 19
System.out.println(solution.getMaxBottles(7, 3)); // Output: 10
System.out.println(solution.getMaxBottles(5, 5)); // Output: 6
}
}
Complexity Analysis
Time Complexity:
The maximum number of operations in the while loop occurs when the value of numExchange is 2. In this case, for each iteration, the number of full bottles decreases by 1 (as 2 full bottles are exchanged for 1 new full bottle). Thus, the overall time complexity of the algorithm is
Space Complexity:
The space complexity is totalDrunkBottles and numBottles).
An Alternate Approach (Optimized Simulation)
In this approach, we keep track of the total number of bottles consumed and repeatedly exchange empty bottles for new full ones until no more exchanges can be made. The process involves drinking all available full bottles, collecting the empty ones, and then trading them for new full bottles if possible. This approach ensures that every possible bottle exchange is utilized, thus maximizing the number of bottles consumed.
Step-by-Step Algorithm
-
Initialize Variables:
- Start with
consumedBottles = 0to keep track of the total number of bottles drunk.
- Start with
-
Loop to Calculate and Perform Exchanges:
- While
numBottles >= numExchange:- Continue as long as we have enough bottles to exchange for a new full bottle.
- While
-
Calculate Maximum Number of Exchanges:
- Compute
K = numBottles / numExchange:- This gives the maximum number of exchanges possible with the current full bottles.
- Compute
-
Update Consumed Bottles and Remaining Full Bottles:
- Add
numExchange * KtoconsumedBottles:- Count the bottles consumed from these exchanges.
- Subtract
numExchange * KfromnumBottles:- Update the number of full bottles after the exchanges.
- Add
KtonumBottles:- Include the new full bottles obtained from the exchanges.
- Add
-
Add Remaining Bottles:
- Return
consumedBottles + numBottles:- Include any remaining full bottles that are less than
numExchange.
- Include any remaining full bottles that are less than
- Return
Algorithm Walkthrough
Input: numBottles = 15, numExchange = 4
-
Initial State:
numBottles = 15consumedBottles = 0
-
First Iteration:
- Calculate the number of exchanges possible:
K = 15 / 4 = 3 - Add the consumed bottles:
consumedBottles = 0 + 4 * 3 = 12 - Subtract the used bottles:
numBottles = 15 - 4 * 3 = 3 - Add the new full bottles:
numBottles = 3 + 3 = 6
- Calculate the number of exchanges possible:
-
Second Iteration:
- Calculate the number of exchanges possible:
K = 6 / 4 = 1 - Add the consumed bottles:
consumedBottles = 12 + 4 * 1 = 16 - Subtract the used bottles:
numBottles = 6 - 4 * 1 = 2 - Add the new full bottles:
numBottles = 2 + 1 = 3
- Calculate the number of exchanges possible:
-
Exit Loop:
- Now
numBottles = 3, which is less thannumExchange = 4, so exit the loop.
- Now
-
Final Addition:
- Add the remaining bottles:
consumedBottles = 16 + 3 = 19
- Add the remaining bottles:
-
Return Result:
- Return
consumedBottles = 19
- Return
Code
class Solution {
public int numWaterBottles(int numBottles, int numExchange) {
int consumedBottles = 0; // This will keep track of the total number of bottles drunk
while (numBottles >= numExchange) {
// Calculate the maximum number of exchanges possible with the current full bottles
int K = numBottles / numExchange;
// Add the number of bottles consumed from these exchanges
consumedBottles += numExchange * K;
// Update the number of full bottles after exchanges
numBottles -= numExchange * K;
// Add the new full bottles obtained from exchanges
numBottles += K;
}
// Add the remaining full bottles that are less than numExchange
return consumedBottles + numBottles;
}
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.numWaterBottles(15, 4)); // Output: 19
System.out.println(sol.numWaterBottles(7, 3)); // Output: 10
System.out.println(sol.numWaterBottles(5, 5)); // Output: 6
}
}
Complexity Analysis
-
Time Complexity: The time complexity of the algorithm is
. This is because in each iteration of the while loop, the number of bottles decreases by a factor of approximately . Thus, the number of iterations is logarithmic with respect to the number of bottles. -
Space Complexity: The space complexity is
. The algorithm uses a constant amount of extra space regardless of the input size.
🤖 Don't fully get this? Learn it with Claude
Stuck on Water Bottles? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Water Bottles** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Water Bottles** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Water Bottles**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Water Bottles**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.