The Water and Jug Problem asks: Given two jugs with capacities x
and y
liters, and an unlimited water supply, determine if it is possible to measure exactly z
liters using these jugs. You can perform the following operations as many times as you like:
x
, y
, and z
are non-negative integers.z
liters (no more, no less).At first glance, this problem seems to require simulating every possible sequence of fills, pours, and empties. This brute-force approach would involve exploring all possible water levels in both jugs, which quickly becomes infeasible for large jug sizes.
However, by thinking mathematically, we realize that the problem is fundamentally about whether we can measure z
liters using any combination of the two jug capacities. This is related to the classic "Diophantine equation" problem, where we look for integer solutions to equations of the form ax + by = z
. The key insight is that using the allowed operations, we can measure any amount of water that is a linear combination of x
and y
.
The conceptual shift is from simulating all possible states to recognizing that the problem reduces to checking if z
is a multiple of the greatest common divisor (GCD) of x
and y
, and is not more than the sum of their capacities.
To solve the problem efficiently, we use these steps:
z
is greater than x + y
, it is impossible to measure z
liters, since that's the maximum water you can have using both jugs.
z
is a multiple of gcd(x, y)
. This is because with the allowed operations, you can only measure amounts that are linear combinations of x
and y
(Bézout's identity).
z
is 0, you can always measure it (by leaving both jugs empty).
gcd(x, y)
.z
is less than or equal to x + y
and z % gcd(x, y) == 0
.true
; otherwise, return false
.This approach is efficient and avoids unnecessary simulation.
Example: x = 3
, y = 5
, z = 4
3 + 5 = 8
. Since z = 4
is less than 8, continue.
gcd(3, 5) = 1
.
4 % 1 == 0
(true).
Brute-force Approach:
gcd(x, y)
takes O(\log(\min(x, y)))
time using the Euclidean algorithm.O(1)
since only a few variables are used.Thus, the optimized solution is highly efficient and suitable for large input sizes.
The Water and Jug Problem can be solved elegantly by recognizing its connection to number theory. Instead of simulating all possible moves, we use the mathematical insight that only amounts that are multiples of the GCD of the jug sizes can be measured, provided the target is not larger than the sum of both jugs. This makes the solution both efficient and conceptually satisfying, turning a seemingly complex problem into a straightforward calculation.
def canMeasureWater(x: int, y: int, z: int) -> bool:
from math import gcd
if z == 0:
return True
if x + y < z:
return False
return z % gcd(x, y) == 0
class Solution {
public:
bool canMeasureWater(int x, int y, int z) {
if (z == 0) return true;
if (x + y < z) return false;
return z % std::__gcd(x, y) == 0;
}
};
class Solution {
public boolean canMeasureWater(int x, int y, int z) {
if (z == 0) return true;
if (x + y < z) return false;
return z % gcd(x, y) == 0;
}
private int gcd(int a, int b) {
while (b != 0) {
int temp = a % b;
a = b;
b = temp;
}
return a;
}
}
var canMeasureWater = function(x, y, z) {
if (z === 0) return true;
if (x + y < z) return false;
function gcd(a, b) {
while (b !== 0) {
let temp = a % b;
a = b;
b = temp;
}
return a;
}
return z % gcd(x, y) === 0;
};