LeetCode 31.水壶问题 数学方法与广度遍历
Posted transkai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 31.水壶问题 数学方法与广度遍历相关的知识,希望对你有一定的参考价值。
题目描述
有两个容量分别为 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
解题思路
数学方法:找到x,y的最大公约数能否z被整除
BFS:将水壶x,y的相关操作分解为6个状态,分别为 // 1.给x装满水 // 2.给y装满水 // 3.清空x的水 // 4.清空y的水 // 5.x向y倒水,直到x空或者y满 // 6.y向x倒水,直到y空或者x满 // 通过不断的搜索,如果x,y中的水满足 // x == z || y == z || x + y == z 返回true,否则继续搜索直到所有情况都搜索完毕
代码如下
数学方法:
public boolean canMeasureWater(int x, int y, int z) {
if(x+y<z){
return false;
}
if(x == 0 || y == 0){
return z==0 || x+y==z;
}
return z % gcb(x,y) == 0;
}
int gcb(int m, int n) {
if (m < n) {// 保证m>n,若m<n,则进行数据交换
int temp = m;
m = n;
n = temp;
}
if (m % n == 0) {// 若余数为0,返回最大公约数
return n;
} else { // 否则,进行递归,把n赋给m,把余数赋给n
return gcb(n, m % n);
}
}
BFS:
public boolean canMeasureWater(int x, int y, int z) { if (z > x + y) return false; if (x == z || y == z || x + y == z) return true; // 保存搜索过的情况,防止无止境的搜索下去 Set<List<Integer>> set = new HashSet<>(); // 保存每次操作后,x,y中剩余的水的容量 LinkedList<List<Integer>> res = new LinkedList<>(); // 初始时,x y中均没有水 List<Integer> list = Arrays.asList(0, 0); set.add(list); res.add(list); while (!res.isEmpty()) { List<Integer> poll = res.poll(); int remain_x = poll.get(0); int remain_y = poll.get(1); if (remain_x == z || remain_y == z || remain_x + remain_y == z) { return true; } // 给x加满水 List<Integer> p1 = Arrays.asList(x, remain_y); if (!set.contains(p1)) { set.add(p1); res.add(p1); } // 给y加满水 List<Integer> p2 = Arrays.asList(remain_x, y); if (!set.contains(p2)) { set.add(p2); res.add(p2); } // 清空x的水 List<Integer> p3 = Arrays.asList(0, remain_y); if (!set.contains(p3)) { set.add(p3); res.add(p3); } // 清空y的水 List<Integer> p4 = Arrays.asList(remain_x, 0); if (!set.contains(p4)) { set.add(p4); res.add(p4); } // x向y倒水 int tmp_x = (remain_x + remain_y) <= y ? 0 : remain_x + remain_y - y; int tmp_y = (remain_x + remain_y) < y ? remain_x + remain_y : y; List<Integer> p5 = Arrays.asList(tmp_x, tmp_y); if (!set.contains(p5)) { set.add(p5); res.add(p5); } // y向x倒水 tmp_y = (remain_x + remain_y) <= x ? 0 : remain_x + remain_y - x; tmp_x = (remain_x + remain_y) < x ? remain_x + remain_y : x; List<Integer> p6 = Arrays.asList(tmp_x, tmp_y); if (!set.contains(p6)) { set.add(p6); res.add(p6); } } return false; }
参考自:LeetCode用户yw-git
以上是关于LeetCode 31.水壶问题 数学方法与广度遍历的主要内容,如果未能解决你的问题,请参考以下文章
算法入门广度优先搜索(中等 - 第二题)LeetCode 116
算法入门广度优先搜索(中等 - 第一题)LeetCode 994
算法入门广度优先搜索(简单 - 第一题)LeetCode 542