You are given two jugs with capacities x
liters and y
liters. You have an infinite water supply. Return whether the total amount of water in both jugs may reach target
using the following operations:
Example 1:
Input: x = 3, y = 5, target = 4
Output: true
Explanation:
Follow these steps to reach a total of 4 liters:
Reference: The Die Hard example.
Example 2:
Input: x = 2, y = 6, target = 5
Output: false
Example 3:
Input: x = 1, y = 2, target = 3
Output: true
Explanation: Fill both jugs. The total amount of water in both jugs is equal to 3 now.
Constraints:
1 <= x, y, target <= 103
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to the Water and Jug problem is like trying every single combination of filling, emptying, and pouring water between the jugs. We essentially simulate all possible actions until we find a combination that gives us the target amount of water in one of the jugs.
Here's how the algorithm would work step-by-step:
def can_measure_water_brute_force(jug_a_capacity, jug_b_capacity, target_capacity):
visited_states = set()
queue = [(0, 0)]
while queue:
current_state = queue.pop(0)
jug_a_amount, jug_b_amount = current_state
# Check if we've reached the target
if jug_a_amount == target_capacity or jug_b_amount == target_capacity or jug_a_amount + jug_b_amount == target_capacity:
return True
# Avoid infinite loops by tracking states
if current_state in visited_states:
continue
visited_states.add(current_state)
# Generate all possible next states
next_states = [
(jug_a_capacity, jug_b_amount), # Fill jug A
(jug_a_amount, jug_b_capacity), # Fill jug B
(0, jug_b_amount), # Empty jug A
(jug_a_amount, 0), # Empty jug B
]
# Pour jug A to jug B
pour_amount = min(jug_a_amount, jug_b_capacity - jug_b_amount)
next_states.append((jug_a_amount - pour_amount, jug_b_amount + pour_amount))
# Pour jug B to jug A
pour_amount = min(jug_b_amount, jug_a_capacity - jug_a_amount)
next_states.append((jug_a_amount + pour_amount, jug_b_amount - pour_amount))
# Add the next states to the queue for processing
queue.extend(next_states)
return False
The most efficient way to solve the water and jug problem isn't about trying random pours. It's about understanding the mathematical relationship between the jug sizes and whether you can actually measure the target amount of water. We determine if a solution is even possible, and then find a way to achieve the solution through a combination of filling, emptying, and transferring water between the jugs.
Here's how the algorithm would work step-by-step:
def can_measure(jug1_capacity, jug2_capacity, target_capacity):
def gcd(a, b):
while b:
a, b = b, a % b
return a
# Impossible if target exceeds combined capacity.
if target_capacity > jug1_capacity + jug2_capacity:
return False
# Check if target is multiple of GCD.
greatest_common_divisor = gcd(jug1_capacity, jug2_capacity)
if target_capacity % greatest_common_divisor != 0:
return False
# At this point the target is potentially achievable.
return True
Case | How to Handle |
---|---|
targetCapacity is greater than the sum of jug1Capacity and jug2Capacity | Return false immediately since it's impossible to measure more than the total capacity of both jugs. |
jug1Capacity or jug2Capacity is zero, and targetCapacity is greater than the other jug's capacity | Return false because it is impossible to measure more than the other jug's capacity when one jug has zero capacity. |
jug1Capacity, jug2Capacity, and targetCapacity are all zero | Return true, as the target of 0 is achievable with empty jugs. |
jug1Capacity or jug2Capacity is zero, and targetCapacity is a multiple of the other jug's capacity | Check if targetCapacity is 0 or a multiple of the non-zero jug's capacity; if so return true, otherwise false. |
jug1Capacity equals jug2Capacity, and targetCapacity is not a multiple of jug1Capacity | Return false if targetCapacity is not a multiple of the equal jug capacities since the gcd will be the jug capacity, which must divide the target. |
targetCapacity is equal to either jug1Capacity or jug2Capacity | Return true immediately, as the target is directly achievable. |
jug1Capacity and jug2Capacity are relatively prime (GCD is 1) | If the target capacity is less than or equal to the sum of the two jugs, return true, as any amount up to the combined capacity is achievable. |
Integer overflow can occur when calculating intermediate water amounts (e.g., pouring) | Use appropriate data types (e.g., long) to avoid overflow issues during calculations or use iterative approach to prevent stack overflow due to recursion. |