@@ -25,7 +25,66 @@ Output: False
2525
2626```
2727
28- ## 思路
28+
29+ ## BFS(超时)
30+
31+ ### 思路
32+
33+ 两个水壶的水我们考虑成状态,然后我们不断进行倒的操作,改变状态。那么初始状态就是(0 0) 目标状态就是 (any, z)或者 (z, any),其中any 指的是任意升水。
34+
35+
36+ 已题目的例子,其过程示意图,其中括号表示其是由哪个状态转移过来的:
37+
38+ 0 0
39+ 3 5(0 0) 3 0 (0 0 )0 5(0 0)
40+ 3 2(0 5) 0 3(0 0)
41+ 0 2(3 2)
42+ 2 0(0 2)
43+ 2 5(2 0)
44+ 3 4(2 5) bingo
45+
46+ ### 代码
47+
48+ ``` python
49+ class Solution :
50+ def canMeasureWater (self , x : int , y : int , z : int ) -> bool :
51+ if x + y < z:
52+ return False
53+ queue = [(0 , 0 )]
54+ seen = set ((0 , 0 ))
55+
56+ while (len (queue) > 0 ):
57+ a, b = queue.pop(0 )
58+ if a == z or b == z or a + b == z:
59+ return True
60+ states = set ()
61+
62+ states.add((x, b))
63+ states.add((a, y))
64+ states.add((0 , b))
65+ states.add((a, 0 ))
66+ states.add((min (x, b + a), 0 if b < x - a else b - (x - a)))
67+ states.add((0 if a + b < y else a - (y - b), min (b + a, y)))
68+ for state in states:
69+ if state in seen:
70+ continue ;
71+ queue.append(state)
72+ seen.add(state)
73+ return False
74+ ```
75+
76+ ** 复杂度分析**
77+
78+ - 时间复杂度:由于状态最多有$O((x + 1) * (y + 1))$ 种,因此总的时间复杂度为$O(x * y)$。
79+ - 空间复杂度:我们使用了队列来存储状态,set 存储已经访问的元素,空间复杂度和状态数目一致,因此空间复杂度是$O(x * y)$。
80+
81+ 上面的思路很直观,但是很遗憾这个算法在 LeetCode 的表现是 TLE(Time Limit Exceeded)。不过如果你能在真实面试中写出这样的算法,我相信大多数情况是可以过关的。
82+
83+ 我们来看一下有没有别的解法。实际上,上面的算法就是一个标准的 BFS。如果从更深层次去看这道题,会发现这道题其实是一道纯数学问题,类似的纯数学问题在 LeetCode 中也会有一些,不过大多数这种题目,我们仍然可以采取其他方式 AC。那么让我们来看一下如何用数学的方式来解这个题。
84+
85+ ## 数学法 - 最大公约数
86+
87+ ### 思路
2988
3089这是一道关于` 数论 ` 的题目,确切地说是关于` 裴蜀定理 ` (英语:Bézout's identity)的题目。
3190
@@ -40,60 +99,61 @@ ax+by=m
4099
41100```
42101
43- 因此这道题可以完全转化为` 裴蜀定理 ` 。
102+ 因此这道题可以完全转化为` 裴蜀定理 ` 。还是以题目给的例子` x = 3, y = 5, z = 4 ` ,我们其实可以表示成` 3 * 3 - 1 * 5 = 4 ` , 即` 3 * x - 1 * y = z ` 。我们用a和b分别表示3
103+ 升的水壶和5升的水壶。那么我们可以:
44104
45- ## 关键点解析
46105
47- - 数论
48- - 裴蜀定理
106+ - 倒满a(** 1** )
107+ - 将a倒到b
108+ - 再次倒满a(** 2** )
109+ - 再次将a倒到b(a这个时候还剩下1升)
110+ - 倒空b(** -1** )
111+ - 将剩下的1升倒到b
112+ - 将a倒满(** 3** )
113+ - 将a倒到b
114+ - b此时正好是4升
49115
50- ## 代码
51- ``` js
116+ 上面的过程就是` 3 * x - 1 * y = z ` 的具体过程解释。
52117
118+ ** 也就是说我们只需要求出x和y的最大公约数d,并判断z是否是d的整数倍即可。**
53119
54- /*
55- * @lc app=leetcode id=365 lang=javascript
56- *
57- * [365] Water and Jug Problem
58- *
59- * https://leetcode.com/problems/water-and-jug-problem/description/
60- *
61- * algorithms
62- * Medium (28.76%)
63- * Total Accepted: 27K
64- * Total Submissions: 93.7K
65- * Testcase Example: '3\n5\n4'
66- *
67- * You are given two jugs with capacities x and y litres. There is an infinite
68- * amount of water supply available. You need to determine whether it is
69- * possible to measure exactly z litres using these two jugs.
70- *
71- * If z liters of water is measurable, you must have z liters of water
72- * contained within one or both buckets by the end.
73- *
74- * Operations allowed:
75- *
76- *
77- * Fill any of the jugs completely with water.
78- * Empty any of the jugs.
79- * Pour water from one jug into another till the other jug is completely full
80- * or the first jug itself is empty.
81- *
82- *
83- * Example 1: (From the famous "Die Hard" example)
84- *
85- *
86- * Input: x = 3, y = 5, z = 4
87- * Output: True
88- *
89- *
90- * Example 2:
91- *
92- *
93- * Input: x = 2, y = 6, z = 5
94- * Output: False
95- *
96- */
120+
121+ ### 代码
122+
123+ 代码支持:Python3,JavaScript
124+
125+
126+ Python Code:
127+
128+ ``` python
129+ class Solution :
130+ def canMeasureWater (self , x : int , y : int , z : int ) -> bool :
131+ if x + y < z:
132+ return False
133+
134+ if (z == 0 ):
135+ return True
136+
137+ if (x == 0 ):
138+ return y == z
139+
140+ if (y == 0 ):
141+ return x == z
142+
143+ def GCD (a , b ):
144+ smaller = min (a, b)
145+ while smaller:
146+ if a % smaller == 0 and b % smaller == 0 :
147+ return smaller
148+ smaller -= 1
149+
150+ return z % GCD(x, y) == 0
151+ ```
152+
153+ JavaScript:
154+
155+
156+ ``` js
97157/**
98158 * @param {number} x
99159 * @param {number} y
@@ -121,3 +181,28 @@ var canMeasureWater = function(x, y, z) {
121181 return z % GCD (x, y) === 0 ;
122182};
123183```
184+
185+ 实际上求最大公约数还有更好的方式,比如辗转相除法:
186+
187+ ``` python
188+ def GCD (a , b ):
189+ if b == 0 : return a
190+ return GCD(b, a % b)
191+ ```
192+
193+ ** 复杂度分析**
194+
195+ - 时间复杂度:$O(log(max(a, b)))$
196+ - 空间复杂度:空间复杂度取决于递归的深度,因此空间复杂度为 $O(log(max(a, b)))$
197+
198+
199+ ## 关键点分析
200+
201+ - 数论
202+ - 裴蜀定理
203+
204+ 更多题解可以访问我的LeetCode题解仓库:https://github.com/azl397985856/leetcode 。 目前已经接近30K star啦。
205+
206+ 大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的LeetCode题解
207+
208+ ![ ] ( https://pic.leetcode-cn.com/89ef69abbf02a2957838499a96ce3fbb26830aae52e3ab90392e328c2670cddc-file_1581478989502 )
0 commit comments