原题链接:https://leetcode.cn/problems/water-and-jug-problem/description/
题目描述:
有两个水壶,容量分别为 jug1Capacity
和 jug2Capacity
升。水的供应是无限的。确定是否有可能使用这两个壶准确得到 targetCapacity
升。
如果可以得到 targetCapacity
升水,最后请用以上水壶中的一或两个来盛放取得的 targetCapacity
升水。
你可以:
- 装满任意一个水壶
- 清空任意一个水壶
- 从一个水壶向另外一个水壶倒水,直到装满或者倒空
输入输出描述:
示例 1:
输入: jug1Capacity = 3, jug2Capacity = 5, targetCapacity = 4 输出: true 解释:来自著名的 "Die Hard"
示例 2:
输入: jug1Capacity = 2, jug2Capacity = 6, targetCapacity = 5 输出: false
示例 3:
输入: jug1Capacity = 1, jug2Capacity = 2, targetCapacity = 3 输出: true
提示:
1 <= jug1Capacity, jug2Capacity, targetCapacity <= 10^6
解题思路:
当一个桶的容量是x,另一个桶的容量是y,那么每次的变化量必然是x或者y,那么这个时候就会有一个疑问了,如果我往一个不满的桶里面倒水或者将水倒掉变化量不就不是x或者y了吗,虽然这样看变化量不是x或者y,但是进一步分析你会发现这种操作实际上是没有意义的。
首先根据题目的三种操作,你可以得出一个结论就是不可能存在俩个桶都不满并且都有水的情况,至少一个桶为空或者为满。
当把一个不满并且有水的桶倒满时,如果另一个桶为空时,此时的状态就相当于从初始状态把这个不满的桶倒满,如果另一个桶为满时,此时的状态就相当于从初始状态把俩个桶都倒满。
当把一个不满的桶倒空时,如果另一个桶为空,那么此时就相当于初始状态,如果另一个桶为满时,那么此时的状态就相当于从初始状态把另一个桶倒满。
当把一个桶的水往另一个桶倒时,俩个桶的总水量是不变的。
通过上述分析我们可以发现,有些操作是没有意义的,我们每次操作水的总量的变化量一定是x或者y,也就是说我们需要找到整数a,b使得ax*by=z。
当x==0,y!=0时,那么此时只能凑出y和0。
当y==0,x!=0时,那么此时只能凑出x和0
当x==0,y==0时,那么此时只能凑出0
当x!=0,y!=0时,那么此时就是找到整数a,b使得ax+by=z,那么看到这个式子,如果学过一点数论的,那么很快就能想到裴蜀定理,裴蜀定理见下面百度百科链接:
裴蜀定理_百度百科
ax+by=gcd(x,y),根据裴蜀定理,这个等式一定存在(a,b)满足这个等式,那么只有当z是gcd(x,y)的倍数时才能凑出z,多少倍就对等式俩边乘以多少即可,这个是不影响等式的成立的。但是这个题目还有一个限制就是最多只能凑出x+y,所以当z>x+y是无解的,需要特判一下这种情况。
时间复杂度:使用gcd函数,时间复杂度为log(min(x,y))。
空间复杂度:O(1)。
cpp代码如下:
class Solution {
public:bool canMeasureWater(int x, int y, int z) {if(x+y<z){ // z>x+y所以无法凑出zreturn false;}if(x==0 || y==0){ return z==0||z==x+y;}return z%gcd(x,y)==0;}
};