您的位置:首页 > 其它

Water and Jug Problem

2016-09-07 19:57 232 查看
题目描述如下

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

我记得之前手机里面有个游戏是这样的,所以一下子理解了题目(题目里面说的是测得z得容积,我觉得可以理解成你往z中倒多少的水能到满),就是通过把杯子x, y, z里的水倒来倒去,最后把z给倒满,有三个要求是

每次接水必须接满

每次倒水必须倒空

将水从一个杯子x倒向另一个杯子y时,除非x空了而或者y满了才能停止。

比如例子 1有两种方法

x接满倒入y中,再接满倒入y中,y满的时候x剩1,将x剩余倒入z中,x接满再倒入中,z正好接满

x接满倒入y中,在接满倒入y中,x水倒掉,y倒入x中,y中剩余2,倒入z;重复以上步骤

因此首先想到的是,有x, y两个罐子我们相当于可以得到

[x, y, y%x, x - y%x]这四个数来组成z,但是.想不到一个好的方法去解决这个问题,四个数的话感觉复杂度好高,这个问题留在这,看书的过程中留个心。

于是换个思维,实际上,所得到的新数是通过

new = m*x + n*y的到的,倒入为+倒出为负,第一个例子的步骤就可以理解为3+3-5+3,即 3*3-5,于是问题就变成了了求解是否存在m,n满足这个等式.

由裴蜀定理(描述的比较通俗)裴蜀定理

对任何整数x、y和它们的最大公约数d,关于未知数m和n的线性丢番图方程(称为裴蜀等式):m∗x+n∗y=z

有整数解时当且仅当z是d的倍数。

现在问题就演变成了求数x与y的最大公约数resid,看它是否能被z整除。

求最大公约数的主要方法有两种:

辗转相除法(欧几里得)核心理论就是:

gcd(x,y)=gcd(y,r)其中r=x mod y

设d=gcd(x,y), x=ky+r−>md=knd+r因此 r=(m−kn)d能被x,y的最大公约数d整除,现需要证明,n 与 m-kn 互质,即可证明y 与 r最大公约数为d。若n 与 m-kn 有某个公约数 l则y 与 r的最大公约数为d*l,与假设不负(没有很严谨的证明哈,只是理解)。

根据此式可以用递归的方法来实现求得公约数,而递归的终止条件就是x mod y=0

当x mod y=0说明x能被y整除,y=gcd(x,y),程序如下

class Solution(object):
def canMeasureWater(self, x, y, z):
dmax = max(x, y)
dmin = min(x, y)
resid = self.gcd(dmax, dmin)
return True if z % resid == 0 else False

def gcd(self, x, y):
return x if
b658
y == 0  else self.gcd(y, x%y)


但是,提交后测试数据中有 0, 0 , 0,再加上限制条件x+y>=z,给你的总容量只有x+y你是没有办法称出大于这个值得水,修改后代码如下,速率beat 99.3%

class Solution(object):
def canMeasureWater(self, x, y, z):
dmax = max(x, y)
dmin = min(x, y)
if dmin ==0 and dmax ==z or z ==0:
return True
elif dmin == 0 and dmax != z or x+y<z:
return False
resid = self.gcd(dmax, dmin)
return True if z % resid == 0 else False

def gcd(self, x, y):
return x if y == 0  else self.gcd(y, x%y)


尴尬….今天才看到原来是leetcode的编译器更新了,所以现在体检的方法总会比之前提交的快很多….所以,这个图没有任何参考性啦

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息