365. 水壶问题

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

思路1:
数学方法。
已知往未满的水壶中倒水是没有意义的,每次操作给水的总量带来的变化为x或y。
因此可以得出存在一个整数a、b满足ax+by=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

思路1:
数学方法。
已知往未满的水壶中倒水是没有意义的,每次操作给水的总量带来的变化为x或y。
因此可以得出存在一个整数a、b满足ax+by=z时,满足题意。
根据裴蜀定理当且仅当z是a、b的最小公约数倍数时有整数解a、b。

代码:
class Solution {
    public boolean canMeasureWater(int x, int y, int z) { 
        if(x == 0 && y == 0) return z == 0;
        return z == 0 || (z % gcd(x,y) == 0 && x + y >= z);
    }
    static int gcd(int x,int y){
        if(y == 0) return x;
        int r = x % y;
        return gcd(y,r);
    }
}

思路2:
总共只有4种操作,将x、y灌满或清空,用哈希表存放所有可能的状态,用队列存放当前存活的各种状态。
通过BFS查找满足题意的操作方法。
代码(某一题解):
class Solution {
    public boolean canMeasureWater(int x, int y, int z) {
//1.边界判断
        if (x + y < z || z < 0) return false;
        //2.存放所有可能的状态,并用来防止重复进入同一状态
        Set<Integer> set = new HashSet<>();
        //3.存放当前存活的各种状态
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(0);
        while (!queue.isEmpty()) {
            int curr = queue.poll();
            //1.将x灌满;(curr + x <= x + y -->说明curr<=y,可以将curr 全部放入 y 中,x此时为空)
            if (curr + x <= x + y && set.add(curr + x))
                queue.offer(curr + x);
            //2.将y灌满
            if (curr + y <= x + y && set.add(curr + y))
                queue.offer(curr + y);
            //3.将x清空
            if (curr - x >= 0 && set.add(curr - x))
                queue.offer(curr - x);
            //4.将y清空
            if (curr - y >= 0 && set.add(curr - y))
                queue.offer(curr - y);
            if (set.contains(z))
                return true;
        }
        return false;
    }
}

 



posted @ 2020-03-21 10:15  zjcfrancis  阅读(265)  评论(0编辑  收藏  举报