题目来源
力扣365水壶问题https://leetcode.cn/problems/water-and-jug-problem/description/
题目概述
有两个水壶,容量分别为 jug1Capacity 和 jug2Capacity 升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 targetCapacity 升。
如果可以得到 targetCapacity 升水,最后请用以上水壶中的一或两个来盛放取得的 targetCapacity 升水。
你可以:
- 装满任意一个水壶
- 清空任意一个水壶
- 从一个水壶向另外一个水壶倒水,直到装满或者倒空
解题思路
首先我们确定在实际上我们只能做的操作:
- 把其中一个杯子装满;
- 把一个杯子里的水倒入另一个杯子,然后清空那个满的杯子(清空不满的杯子没有意义,我们可以直接装满一个杯子,哈哈哈哈)。
我们记水的总量为sum,sum = a × jug1Capacity + b × jug2Capacity。(a >= 0 && b >= 0)。 由此可知,我们会有无穷多个计算sum的表达式。 当某一个sum == targetCapacity时我们应该返回结果为true,这时可以使用贝祖定理(裴蜀定理)来解决问题:
对任意两个整数a、b设d是它们的最大公约数。ax + by = m有整数解(x,y)当且仅当m是d的倍数。
总结
我们只需要确定targetCapacity为jug1Capacity和jug2Capacity的最大公约数的倍数,那就返回结果true,反之返回false。 关于求最大公约数的题目以前做过可以使用欧几里德算法求。【每日一题博客】力扣2807在链表中插入最大公约数
代码实现
java实现
public class Solution {
public boolean canMeasureWater(int jug1Capacity, int jug2Capacity, int targetCapacity) {
// 如果两个杯子都装满也不够
if (jug1Capacity + jug2Capacity < targetCapacity) {
return false;
}
// 欧几里得算法求最大公约数
int remainder = jug1Capacity % jug2Capacity;
while (remainder != 0) {
jug1Capacity = jug2Capacity;
jug2Capacity = remainder;
remainder = jug1Capacity % jug2Capacity;
}
// 最终jug2保存的是两个容量的最小公约数
return targetCapacity % jug2Capacity == 0;
}
}
c++实现
这里c++的代码跟java完全一样的
class Solution {
public:
bool canMeasureWater(int jug1Capacity, int jug2Capacity, int targetCapacity) {
// 如果两个杯子都装满也不够
if (jug1Capacity + jug2Capacity < targetCapacity) {
return false;
}
// 使用欧几里得算法求最大公约数
int remainder = jug1Capacity % jug2Capacity;
while (remainder != 0) {
jug1Capacity = jug2Capacity;
jug2Capacity = remainder;
remainder = jug1Capacity % jug2Capacity;
}
// 最终jug2保存的是两个容量的最小公约数
return targetCapacity % jug2Capacity == 0;
}
};