[题记-数学-最大公约数]水壶问题-leetcode

题目:水壶问题

有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?

如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。

你允许:

  • 装满任意一个水壶
  • 清空任意一个水壶
  • 从一个水壶向另外一个水壶倒水,直到装满或者倒空

示例 1: (From the famous "Die Hard" example)

输入: x = 3, y = 5, z = 4
输出: True

示例 2:

输入: x = 2, y = 6, z = 5
输出: False



数学方法用到一个定理定理:贝祖定理

用简单的话说一下这个定理就是:
  存在这么一个式子: ax + by = z,如果这个式子有解,那么z一定是x,y的最大公约数的倍数。


回来看我们的题目:
当然可以用搜索的方式去解,这里推荐用数学方法(来自官方解答)。

通过题目要求,我们可以认为每次操作只会让壶里的水增加x或y,减少x或y。
那么如果往没满的壶中加水或者排空呢?
  1. 根据题目要求不可能会出现两个桶有水并且都不满
  2. 对一个不满的水壶加满是没有意义的:如果另一个壶是空的,这个操作等于从初始状态加满这壶水;如果另一个壶是满的,这个操作等于从初始状态把两个壶都加满。
  3. 对一个不满的水壶清空也是没有意义的:如果另一个壶是空的,这个操作就等于回到初始状态;如果另一个壶是满的,这个操作等于从初始状态将另一个壶加满。

 

这样,我们就可以认为每次操作只会给水的总量带来x,y的变化,那么我们可以吧目标改为:

找到一对a,b使得:ax + by = z

如果 z <= x + y 我们的目标就可以达成

 

原因是:

  1. 若 a >= 0,b >= 0 显然可以达成目标
  2. 若 a < 0 可以进行以下操作:
    • 给 y 壶倒水
    • 把 y 壶的水倒入 x 壶中,如果 y 壶不为空,那就将 x 壶清空, y 壶继续往 x 壶倒水,重复以上步骤,直到 x 壶进行了 a 次清空,y 壶进行了 b 次倒水。
  3. 若 b < 0 同2。

由贝祖定理得出:ax + by = z,如果这个式子有解,那么z一定是x,y的最大公约数的倍数。

上代码(c):

bool canMeasureWater(int x, int y, int z){
    if( x + y < z ) return false;
    if( x == 0|| y == 0 ) {
        if( z == 0 ) return true;
        else if( x + y == z ) return true;
        else return false;
    }
    //寻找最大公约数
    while( y > 0 ){
        int tmp = x;
        x = y;
        y = tmp%y;
    }
    if( z%x == 0 ) return true;
    else return false;
}

 

2020-03-21-14:24:05

 





posted @ 2020-03-21 14:26  橙橙橙澄xs  阅读(306)  评论(0)    收藏  举报