精华内容
下载资源
问答
  • LeetCode 水壶问题 贝祖定理
    2021-11-14 15:07:59

    贝祖定理:ax+by=z 有解当且仅当 zz 是 x, yx,y 的最大公约数的倍数(a,b,x,y,z都是整数)

    更多相关内容
  • LeetCode 水壶问题

    千次阅读 2019-03-14 19:28:18
    有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 你允许: 装满任意一个水壶 清空...

    有两个容量分别为 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
    

    思路分析:我刚开始拿到这道题时,一脸懵逼,总想着在脑海中想出整个过程。。。
    将上面的问题转换为数学就是 mx + ny = z的问题,即3m + 5n == 4
    数学中有个定理:

    如果gcd(x,y) = k //gcd函数用以计算两个数的最大公约数greatest common divisor简写 
    那么肯定有整数(正的或负的)m与n,使得 mx + ny = k
    

    如果z % k == 0, 那么mx + ny = k那么必定存在一个常数g使得g(mx + ny) == k * g == z
    所以题目就转换为寻找x,y的最大公约数。

    class Solution {
    public:
        bool canMeasureWater(int x, int y, int z) {
            //首先处理几种特殊情况
            if (z == 0 || x + y == z){
                return true;
            }
            else if (x + y < z){
                return false;
            }
            //确保x < y
            if (x > y){
                int tempVal = x;
                x = y;
                y = tempVal;
            }
            if (x == 0){
                return y == z;
            }
            //寻找最大公约数,辗转相除法
            int val = x;
            while (y % x != 0){
                val = y % x;
                y = x;
                x = val;
            }
            return z % val == 0;
        }
    };
    

    在这里插入图片描述
    我们用示例一,看下怎么得到z。

     1. 初始x,y == 0
     2. x为空,将x倒满 x == 3,y==0
     3. 将x中的水倒入y中,x == 0, y == 3
     4. 将x倒满x == 3,y ==3
     5. 将x中的水倒入y中,直到y满,x == 1,y == 5
     6. 此时y满了,将y中的水全部倒出,x == 1,y == 0
     7. 将x中的水倒入y中,x == 0,y == 1
     8. x为空,将x倒满,x == 3,y == 1,x + y == 4,结束
    

    现在讲上面的过程进行抽象:

    如果x + y != z,一直循环(假设x < y && x,y能够倒出z)
    
     1. 如果x +y == z,退出
     2. 如果x == 0,x倒满,循环
     3. 如果y 满了,y全部倒掉,循环
     4. 尝试将x全部倒入y,直到y满,循环
    

    也可以将y中的水倒入x中

     1. 初始x,y == 0
     2. y为空,将y倒满 x == 0,y==5
     3. 将y中的水倒入x中,x == 3, y == 2
     4. x中满了,x全部倒掉,x== 0,y == 2
     5. 将y中的水倒入x中,直到y满,x == 2,y == 0
     6. 此时y空了,将y倒满,x == 2,y == 5
     7. 将y中的水倒入x中,x == 3,y == 4
     8. x满了,x全部倒掉,x == 0,y == 4,x + y == z == 4,退出
    

    进行抽象

        如果x + y != z,一直循环(假设x < y && x,y能够倒出z)
        
         1. 如果x +y == z,退出
         2. 如果y == 0,y倒满,循环
         3. 如果x 满了,x全部倒掉,循环
         4. 尝试将y全部倒入x,直到x满,循环
    
    展开全文
  • leetcode 365题 水壶问题

    2020-03-21 18:06:04
    个人博客中有本文原文...leetcode 365题 水壶问题 题目 有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中...

    个人博客中有本文原文https://whatghost.github.io/2020/03/21/leetcode-365/
    如果喜欢可以访问个人博客WhatGhost.github.io,会有更多分享内容

    leetcode 365题 水壶问题

    题目

    有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?
    如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。
    你允许:
    · 装满任意一个水壶
    · 清空任意一个水壶
    · 从一个水壶向另外一个水壶倒水,直到装满或者倒空

    示例 1:
    
    输入: x = 3, y = 5, z = 4
    输出: True
    
    示例 2:
    
    输入: x = 2, y = 6, z = 5
    输出: False
    

    解题思路

    这个问题最初始的解法就是深度优先搜索,这里不再详细介绍,网上有很多代码和方法
    在查看题解的时候发现有一个很巧妙的方法,在这里分享

    就是用数学方法来做,因为题目要求,不存在两个桶都不满的情况,所以我们每次的操作都只会对整体水量添加或减少x或者是y的水量
    把不满的桶倒掉,如果另一桶是满的,相当于从空直接向另一桶灌满的操作,若果另一桶是空的,则相当于回归到最初的空状态
    把不满的桶灌满,如果另一桶是满的,相当于从空直接把两个桶灌满的操作,若果另一桶是空的,则相当于把这个桶灌满的操作

    所以我们可以得出这个问题其实就是求解方程
    a x + b y = z ax+by=z ax+by=z
    而这个方程有解的条件是z是gcd(x,y)的倍数
    所以这个问题就转换成了求最大公因子的问题

    代码实现

    下述代码中gcd是求最大公因子的代码,当然也可以用c++自带的__gcd()函数

    class Solution {
    public:
        bool canMeasureWater(int x, int y, int z) {
            if(x==0||y==0){
                if(z==0||x+y==z){
                    return true;
                }
                return false;
            }
            if(z%gcd2(x,y)==0&&x+y>=z){
                return true;
            }
            return false;
        }
        inline int gcd2(int a,int b) {
            if(b) while((a%=b) && (b%=a));
                return a+b;
        }
    };
    
    展开全文
  • leetcode-水壶问题

    2020-03-21 20:18:33
     题目来自LeetCode,链接:水壶问题。具体描述为:有两个容量分别为x升和y升的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好z升的水?如果可以,最后请用以上水壶中的一或两个来盛放取得的z...

     题目来自LeetCode,链接:水壶问题。具体描述为:有两个容量分别为x升和y升的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好z升的水?如果可以,最后请用以上水壶中的一或两个来盛放取得的z升水。你允许:

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

     示例1:

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

     示例2:

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

     首先,可以用一个二元组(X中水量,Y中水量)表示在任意一个时刻的状态。每个时刻都有以下几个可选操作:

    • 把X的水倒进Y,直至Y满或X空;
    • 把Y的水倒进X,直至X满或Y空;
    • 把X装满;
    • 把Y装满;
    • 把X倒空;
    • 把Y倒空。

     因此,本题可以使用深度优先搜索BFS来解决。在每一步搜索时,依次尝试上述所有的操作,递归地搜索下去。同时还需要用一个哈希表存储所有已经搜索过的状态,从而保证每个状态至多只被搜索一次。

     JAVA版代码如下:

    class Solution {
        public boolean canMeasureWater(int x, int y, int z) {
            Set<String> set = new HashSet<>();
            Queue<int[]> queue = new LinkedList<>();
            queue.offer(new int[] {0, 0});
            while (!queue.isEmpty()) {
                int[] item = queue.poll();
                if (item[0] == z || item[1] == z || item[0] + item[1] == z) {
                    return true;
                }
                if (!set.add(item[0] + "," + item[1])) {
                   continue;
                }
                queue.offer(new int[] {x, item[1]});
                queue.offer(new int[] {item[0],y});
                queue.offer(new int[] {0, item[1]});
                queue.offer(new int[] {item[0], 0});
                queue.offer(new int[] {Math.max(0, item[0] - (y - item[1])), Math.min(item[1] + item[0], y)});
                queue.offer(new int[] {Math.min(item[0] + item[1], x), Math.max(0, item[1] - (x - item[0]))});
            }
            return false;
        }
    }
    

     这个直接就超时了,因为状态还是有点太多了啊。

     然后参考评论区的一种简单BFS。这里不去关注(X中水量,Y中水量)这个二元状态,改为关注总水量n。那么每次操作只会让桶里的水总量增加 x,增加 y,减少 x,或者减少 y。原因在于在题目所给的操作下,两个桶不可能同时有水且不满。

    • 首先,每次操作后都至少有一个桶是空的或者满的。
    • 其次,对一个不满的桶加水是没有意义的。因为如果另一个桶是空的,那么这个操作的结果等价于直接从初始状态给这个桶加满水;而如果另一个桶是满的,那么这个操作的结果等价于从初始状态分别给两个桶加满。所以这种增加量不是x或y的操作是无意义的。
    • 再次,把一个不满的桶里面的水倒掉是没有意义的。因为如果另一个桶是空的,那么这个操作的结果等价于回到初始状态;而如果另一个桶是满的,那么这个操作的结果等价于从初始状态直接给另一个桶倒满。所以这种减少量不是x或y的操作也是无意义的。

     有了上面的分析,现在我们就只有四个状态了,同样可以用BFS:

    • 增加x:相当于给X加满水,所以须满足n ≤ \le y以将全部水先转移到Y;
    • 增加y:相当于给Y加满水,所以须满足n ≤ \le x以将全部水先转移到X;
    • 减少x:相当于倒掉X的水,所以须满足n ≥ \ge x以能先装满X再倒掉;
    • 减少y:相当于倒掉Y的水,所以须满足n ≥ \ge y以能先装满Y再倒掉。

     JAVA版代码如下:

    class Solution {
        public boolean canMeasureWater(int x, int y, int z) {
            Set<Integer> set = new HashSet<>();
            Queue<Integer> queue = new LinkedList<>();
            queue.offer(0);
            while (!queue.isEmpty()) {
                int n = queue.poll();
                if (n == z) {
                    return true;
                }
                if (n <= y && set.add(n + x)) {
                    queue.offer(n + x);
                }
                if (n <= x && set.add(n + y)) {
                    queue.offer(n + y);
                }
                if (n >= x && set.add(n - x)) {
                    queue.offer(n - x);
                }
                if (n >= y && set.add(n - y)) {
                    queue.offer(n - y);
                }
            }
            return false;
        }
    }
    

     提交结果如下:


     最后是数学解法。因为可以认为每次操作只会给水的总量带来x或者y的变化量,所以可以把目标改写成:找到一对整数 a,和b使得 a x + b y = z ax+by=z ax+by=z。而只要满足 z ≤ x + y z\leq x+y zx+y,且这样的a和b存在,那么就可以达成目标。这是因为:

    • a ≥ 0 a\geq 0 a0 b ≥ 0 b\geq 0 b0,那么显然可以通过倒满a次X和b次Y达成目标。

    • a < 0 a\lt 0 a<0,那么可以进行以下操作:

      • 往Y倒水;
      • 把Y的水倒入X;
      • 如果Y不为空,那么X肯定是满的,把X倒空,然后再把Y的水倒入X以保证Y是空的。

      重复以上操作直至某一步时将X倒空了a次,给Y倒了b次水。

    • b < 0 b\lt 0 b<0,方法同上,x 与 y 互换。

     然后就需要用到数学定理了,根据贝祖定理, a x + b y = z ax+by=z ax+by=z有解当且仅当z是x和y的最大公约数的倍数。因此我们只需要找到 x和y的最大公约数并判断z是否是它的倍数即可。

     JAVA版代码如下:

    class Solution {
        private int gcd(int x, int y) {
            while (true) {
                if (x % y == 0) {
                    return y;
                }
                else {
                    int temp = y;
                    y = x % y;
                    x = temp;
                }
            }
        }
        public boolean canMeasureWater(int x, int y, int z) {
            if (x + y < z) {
                return false;
            }
            if (x == 0 || y == 0) {
                return z == 0 || z == x + y;
            }
            int n = x > y ? gcd(x, y) : gcd(y, x);
            return z % n == 0;
        }
    }
    

     提交结果如下:


    展开全文
  • Leetcode365 水壶问题

    2020-03-21 17:01:04
    leetcode 水壶问题 水壶问题 每日一题,有点偏数学,但是可以用图论的BFD 和DFS 求解。 关于二叉树的BFS和DFS已经进行过介绍,本文主要是图论的BFS和DFS。 首先对题目进行建模。观察题目可知,在任意一个时刻,此...
  • 1、参考了leetcode别人的解题思路,两个水壶实际是最大公约数问题(确实没有想到),反推好像也没有毛病。 2、搞清楚了最大公约数,这道题最大的问题就是边界问题,包括Z超出x+y的边界,x,y ==0的情况,以及x和y...
  • leetcode 365. 水壶问题

    2020-03-21 21:33:56
    水壶问题 题目详情 题目链接 有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 你...
  • 题目描述: 有两个容量分别为 x升 和 y升 的水壶以及无限多...水壶问题就是两个壶的最小公约数与想得到的水的升数是否成倍数问题(除去几个特殊情况,特殊情况在代码中有写到) 当z是最小公约数的整数倍时,可以利用两
  • [leetcode]水壶问题

    2020-04-30 01:27:35
    题目 水壶问题 有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 你允许: 装满任意...
  • 水壶问题 1 题目描述(Leetcode题目链接)   有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得...
  • 有两个容量分别为x升 和y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好z升的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的z升水。 你允许: 装满任意一个水壶 清空任意一...
  • 有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 你允许: 装满任意一个水壶 清空...
  • 水壶问题 有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 你允许: 装满任意一个...
  • LeetCode 365. 水壶问题

    2020-03-21 11:31:04
    有两个容量分别为x升 和y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的z升水。 你允许: 装满任意一个水壶 清空...
  • 有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 你允许: 装满任意一个水壶 清空...
  • LeetCode 目录 LeetCode 4:寻找两个有序数组的中位数 【困难】【二分】 LeetCode 54:螺旋矩阵Ⅰ LeetCode 59:螺旋矩阵 Ⅱ LeetCode 111: 二叉树的最小深度【递归/非递归求解/队列】 LeetCode 149:一条直线上最多的...
  • Leetcode0365. 水壶问题(medium,数学方法,DFS),Python题解
  • 水壶问题 有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 你允许: 装满任意一个...
  • 365. 水壶问题 https://leetcode-cn.com/problems/water-and-jug-problem/ 有两个容量分别为x升 和y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好z升 的水? 如果可以,最后请用以上...
  • leetcode:那些年我遇到过的编程题007:水壶问题 实话实说,想了还挺久,思路停留在把每一个操作转化为计算机语言,没有找到最后判定false的点,那么思路一定是有问题的或者错误的,前边的也没有意义了。看了下答案...
  • 水壶问题 有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 你允许: 装满任意一个...
  • Java实现 LeetCode 365 水壶问题

    万次阅读 多人点赞 2020-03-10 19:09:46
    365. 水壶问题 有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 你允许: 装满任意...
  • 365 水壶问题 广度优先搜索 我们要用一种方式来表示当前两个水壶的状态,这里可以自己选择,比如利用字符串,把两个水壶当前的水量用下划线拼接起来。我这选择的构造一个新的类 Pair private class Pair { int x; ...
  • class Solution { public boolean canMeasureWater(int x, int y, int z) { // 判断特例 if(x + y < z) return false; if(x == z || y == z || x + y == z) return true; return z % help(x, y) == 0;...
  • leetcode365.水壶问题

    2020-03-22 16:48:55
    有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水? 如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。 你允许: 装满任意一个水壶 清空...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 394
精华内容 157
关键字:

leetcode水壶问题