Leetcode 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
Credits:
Special thanks to @vinod23 for adding this problem and creating all test cases.
Next challenges:
思路:命题1:如果a和b互质,则通过题目中的3种基本操作,我们可以实现[0, a+b]之间的任意一个容量。如果命题1正确,那么对于z=gc,x=ga,y=gb,且x+y>=z,我们有c属于[0, a+b],则z就是满足解。下面证明命题1的正确性。
证明:假设a<=b,如果填满a和b,那么就有总容量a+b。然后每次倒掉a直到不能倒为止,此时我们可以得到的容量c有
a + b, b, b - a, b - 2a, ... , b % a
最后我们将剩下的b%a倒入a,现在分别有b%a和b容量,总容量为b%a+b。然后我们每次倒掉a,直至不能倒为止,最后得到的容量是(b%a+b)%a=(b%a+b%a)=(2b)%a此时我们可以得到的容量c有
b + b % a, b + b % a - a, b + b % a - 2a, ... , (2b) % a
重复以上操作a次,可以得到c:
b + (2b) % a, b + (2b) % a - a, b + (2b) % a - 2a, ..., (3b) % a
:
:
:
b + ((a-1)b) % a, b + ((a-1)b) % a - a, b + ((a-1)b) % a - 2a, ... , (ab) % a
其中(ab)%a=0
命题2:集合 { b % a, (2b) % a, (3b) % a, ... , ((a-1)b) % a }
和{ 1, 2, 3, 4, 5, ... , a - 1 }
等价
假设命题2错误,则有m!=n都属于[1,a-1]并且(mb)%a==(nb)%a,则有((m-n)b)%a=0,则有(m-n)%a*b%a=0,则有(m-n)%a=0,则有m=n,与假设矛盾,所以命题2正确。因此上述a+1操作后形成的阵列的最后一列可以取到[0,a-1],倒数第2列可以取到[a,2a-1]....因此整个阵列可以取到[0,a+b]的值,所以命题1正确。
注意上述的阵列a和b同时扩大g倍,则整个阵列可以取到的值就是[0,g,2g,...,(a+b)g]。
那么对于z=gc,x=ga,y=gb,且x+y>=z,我们有c属于[0, a+b],则z就是满足解。
代码:
1 public class Solution { 2 public boolean canMeasureWater(int x, int y, int z) { 3 return z == 0 || z <= (long)x + y && z % GCD(x, y) == 0; 4 } 5 public int GCD(int x, int y) { 6 return x == 0 ? y : GCD(y%x, x); 7 } 8 }