题目地址:
https://www.lintcode.com/problem/water-and-jug-problem/description
给定两个瓶子的容积
x
x
x和
y
y
y,再给定一个非负整数
z
z
z,每次可以进行如下操作:
1、将某个瓶子灌满或放空;
2、将其中一个瓶子向另一个瓶子灌水,直到其中一个瓶子满或者空。
问是否能经过若干次操作可以得到
z
z
z水量的水。”得到“的意思是,要么其中某个瓶子里的水恰好是
z
z
z,要么两个瓶子里的水的和是
z
z
z。两个瓶子一开始都是空的。
详细思路和证明参考https://blog.csdn.net/qq_46105170/article/details/108655271。这里简要说明一下思路。
首先任意时刻两个瓶子的总水量一定是形如 a x + b y ax+by ax+by的形式,并且任意时刻一定有其中一个瓶子是满的或者空的,这一点可以用数学归纳法证明。接着只需要考虑是否存在这样的 a a a和 b b b使得 z = a x + b y z=ax+by z=ax+by了,由Bezout定理知道,这个等价于 gcd ( x , y ) ∣ z \gcd(x,y)|z gcd(x,y)∣z。并且注意,还需要排除 z > x + y z>x+y z>x+y的情况。代码如下:
public class Solution {
/**
* @param x: the given number x
* @param y: the given number y
* @param z: the given number z
* @return: whether it is possible to measure exactly z litres using these two jugs
*/
public boolean canMeasureWater(int x, int y, int z) {
// Write your code here
if (z > x + y) {
return false;
}
return z % gcd(x, y) == 0;
}
private int gcd(int x, int y) {
if (x < y) {
int tmp = x;
x = y;
y = tmp;
}
while (y != 0) {
int r = x % y;
x = y;
y = r;
}
return x;
}
}
时间复杂度 O ( log min ( x , y ) ) O(\log \min(x,y)) O(logmin(x,y)),空间 O ( 1 ) O(1) O(1)。