【经典算法题】水壶问题

【经典算法题】水壶问题

Leetcode 0365 水壶问题

题目描述:Leetcode 0365 水壶问题

【经典算法题】水壶问题_第1张图片

分析

  • 本题的考点:数学、欧几里得算法

  • 两个水壶记为A、BA、B这两个水壶都是及不空也不满,这种情况是不可能存在的。这是因为我们的三种操作所决定的。

  • 我们考虑将两个水壶看成一体,考虑整个整体和外界交换的水量,在最优操作情况下(即操作次数最少的情况下),每次和外界交换的水量只可能是+x、-x、+y、-y。原因如下:假设现在A中有水但是不满,则B中要么是空要么是满,此时将A加满或者将A倒空和外界交换的水量不是上述情况,如果这样操作可以得到解,不如上来直接让A为空或者为满,这样操作次数更少。

  • 考虑这个整体和外界交换水量为x、y的次数分别为a、b,如果有 a × x + b × y = = z a \times x + b \times y ==z a×x+b×y==z,则说明存在解。

  • 因此我们需要判断是否存在这样的a、b使得 a × x + b × y = = z a \times x + b \times y ==z a×x+b×y==z,这就是裴淑定理。可以参考:扩展欧几里得算法。

  • 这里如果x、y的最大公约数可以整除c,就存在a、b

  • 那我们能构造出这组解吗?如果z>x+y,说明一定不存在解。否则可以构造出这组解。下面给出构造过程:

    (1)首先a、b不可能都小于0,因为右侧是c是大于0的,如果a、b都大于0,则说明a、b都等于1,z=x+y

    (2)当有一个大于0,一个小于等于0时,比如a>0,b<=0,则我们可以向A中加满水,然后将A中的水倒到B中,直到水壶A被加了a次水,水壶B倒掉了b次水既可以得到结果。

代码

  • C++
class Solution {
public:
    bool canMeasureWater(int x, int y, int z) {
        if (z > x + y) return false;
        return !z || z % gcd(x, y) == 0;
    }

    int gcd(int a, int b) {
        return b ? gcd(b, a % b) : a;
    }
};
  • Java
class Solution {
    public boolean canMeasureWater(int x, int y, int z) {
        if (z > x + y) return false;
        return z == 0 || z % gcd(x, y) == 0;
    }

    private int gcd(int a, int b) {
        return b != 0 ? gcd(b, a % b) : a;
    }
}

时空复杂度分析

  • 时间复杂度: O ( l o g ( n ) ) O(log(n)) O(log(n))n为求最大公约数的数的大小。

  • 空间复杂度: O ( 1 ) O(1) O(1)

你可能感兴趣的:(经典算法题,欧几里得算法)