題目來源:https://leetcode-cn.com/problems/water-and-jug-problem/python
有兩個容量分別爲 x 升和 y 升的水壺以及無限多的水。請判斷可否經過使用這兩個水壺,從而能夠獲得剛好 z 升的水?bash
若是能夠,最後請用以上水壺中的一或兩個來盛放取得的 z 升水。微信
你容許:ide
示例 1: (From the famous "Die Hard" example)spa
輸入: x = 3, y = 5, z = 4 輸出: True
示例 2:code
輸入: x = 2, y = 6, z = 5 輸出: False
思路:裴蜀定理blog
裴蜀定理是關於最大公約數的定理。ip
對於任何整數 a、b 和 m,d 爲 a 及 b 的最大公約數,關於未知數 x 和 y 的線性不定方程:leetcode
$$ax + by = m$$get
有整數解時,當且僅當 m 是 a 及 b 的最大公約數 d 的倍數。
審題可得:其實每次操做能夠認爲是讓壺裏的水總量增長 x,增長 y,減小 x,減小 y。
這裏涉及到一個壺的水不空的狀況下,那麼對於上面的結論來講明顯是不成立。不着急,這裏解釋下:
對於示例 1,題目給出 x = 3, y = 5, z = 4。
嘗試如何讓壺盛放 4 升的水。(這裏將可盛放 x 升水的壺設爲 A,可盛放 y 升水的壺設爲 B,形如 (0, 0),表示兩個壺盛放的水)
這個時候 ,B 壺中的水爲 4 升,便是所求得結果。
因此這裏就能夠明確前面所得的結論:每次操做,水的總量只會帶來 x 或 y 的變化量。
如今咱們將問題轉化爲求一對整數 a,b,使得
$$ax + by = z$$
只要知足 $z \leq x+y$,表示目標可得。
注意,這裏跟上面的裴蜀定理的式子有所不一樣,這裏 a,b 表示所需求得的目標,而 x,y 已知。(與裴蜀定理式子恰好反過來)。
由題可知:
當 $a \geq 0, b \geq 0$ 時,可求得目標;
當 $a<0$ 時,則須要進行如下操做:(延用上面的 A 壺,B 壺)
重複上面的操做,直到對 A 壺進行 a 次清空,而對 B 壺進行 b 次倒水操做。
當 $b<0$ 時,跟上面的狀況相似,將對 A 壺和 B 壺的操做調換過來便可。
根據裴蜀定理, $ax+by=z$ 有解,當且僅當 z 是 x,y 的最大公約數的倍數。因此咱們只要找到 x,y 的最大公約數,而後判斷 z 是不是這個最大公約數的倍數便可求得答案。
class Solution: def canMeasureWater(self, x: int, y: int, z: int) -> bool: import math if x + y < z: return False if x == 0 or y == 0: return z == 0 or x + y == z return z % math.gcd(x, y) == 0
以上就是根據裴蜀定理,求最大公約數,判斷是否有解來解決《水壺問題》的主要內容。
歡迎關注微信公衆號《書所集錄》