2018年10月21日
#365. Water and Jug Problem
问题描述:
You are given two jugs with capacities x and y litres. There is an infinite amount of water supply available. You need to determine whether it is possible to measure exactly z litres using these two jugs.
If z liters of water is measurable, you must have z liters of water contained within one or both buckets by the end.
Operations allowed:
- Fill any of the jugs completely with water.
- Empty any of the jugs.
- Pour water from one jug into another till the other jug is completely full or the first jug itself is empty
样例:
Example 1: (From the famous "Die Hard" example)
Input: x = 3, y = 5, z = 4
Output: True
Example 2:
Input: x = 2, y = 6, z = 5
Output: False
问题分析:
本题难度为Medium!已给出的函数定义为:
class Solution:
def canMeasureWater(self, x, y, z):
"""
:type x: int
:type y: int
:type z: int
:rtype: bool
"""
其中x、y和z都是整型变量;
本题为经典的水壶问题,且问题只需要判断是否能得到相应的水而不是给出具体的操作顺序,所以问题难度并不高。由于只有两个容量为x和y的水壶,若可以通过这两个水壶得到容量为z的水,则易知z=ax+by,其中a和b都是整数(这里不给出证明,但是这是容易水壶问题得出的结论)。到这里,可以循环查找对应的a和b值,但是很可能要循环很多次(例如10000*10000次),或者循环了很多次也没找到对应的a和b值,但是不能确定下一次就不是答案而停止循环,所以这种方法不是最佳。
其实可以通过x和y的最大公约数来判断,比如说g为x和y的最大公约数,则x=ng且y=mg,其中n和m都是整数,则z=ax+by=ang+bmg=(an+bm)g,即g是z的约数,所以问题的变为求x和y的最大公约数g及判断其是否为z的约数。而求最大公约数可以用辗转相除法来求。
另外,还需要考虑几种情况:
- 若x和y的和小于z(x+y<z),则永远无法得到z升的水,除非有一个容器可以装水(则不符合题意);
- 若z为0,则一定可以得到0升的水。
代码实现:
#coding=utf-8
class Solution:
def canMeasureWater(self, x, y, z):
"""
:type x: int
:type y: int
:type z: int
:rtype: bool
"""
def GCD(x,y):
if not y:
return x
else:
return GCD(y,x%y)
if x+y<z or (z!=0 and z%GCD(x,y)):
return False
else:
return True