python辗转相除_python(四):辗转相除
摘要:
學習leetcode_365: Water and Jug Problem的解法:輾轉相除相關內容(最大公約數、裴蜀定理、歐幾里得算法和擴展歐幾里得算法)。
正文:
1、問題描述
You are given two jugs with capacities x and y litres. There is an infinite amount of water supply available. You need to determine whether it is possible to measure exactly z litres using these two jugs.
If z liters of water is measurable, you must have z liters of water contained within one or both buckets by the end.
Operations allowed:Fill any of the jugs completely with water.
Empty any of the jugs.
Pour water from one jug into another till the other jug is completely full or the first jug itself is empty.
Example 1:
Input: x = 3, y = 5, z = 4
Output: True
(**分析**):
首先,將三個操作進行“量化”,一次倒滿已知體積的壺的操作,相當于有一個(+1)*Volume,而一次將滿壺水倒掉的操作,則相當于(-1)*Volume。這意味著結果可以表示為兩個已知體積壺的整數線性組合:
所以,任意給定(x, y, z)且z
2、整數解存在的判據:裴蜀定理
前述方程是否有整數解的解法有一個已經存在的定理(裴蜀定理),其結論是該方程有整數解(m, n)的充要條件是z為x與y的最大公約數gcd(x, y)的倍數。也就是說,如果這個方程有整數解,那么z一定是
,反過來看,也只有當z%gcd(x,y)=0時,整數解才存在。于是,這個問題轉化為求x和y的最大公約數,有輾轉相除法(歐幾里得算法):
(2.1)核心思想,是如下等式,對于正整數p和q(若p>q),p除以q的余數為r,則有:
由于顯然有p>q>r,這個等式將兩個較大數的公約數求解轉化為兩個較小數的公約數;
(2.2)這個最大公約數等式可以往下繼續寫:
其中從第一個等式開始,后式括號里的第一項為前式括號里的較小數、第二項為前式括號里較大數和較小數相除的余數。最后總能到一個余數為0的情況,此時的第一項即為p和q的最大公約數;
(2.3)這個算法可以用遞歸的思想很好地表達出來,python代碼如下:
test of gcd:這兩組數的最大公約數都是6
那么,leetcode_365就迎刃而解了,代碼如下:
test of canMeasureWater:題目的example隨機輸入3個正整數進行測試
3、整數解的求解:擴展歐幾里得算法
判斷了能否測量,進一步就會思考如何進行測量呢?這個實際上就是在求前述方程的整數解。這里的解法類似于輾轉相除法,也即擴展歐幾里得算法。需要注意的是,由于px+qy=c的整數解從幾何意義上來說是檢查一條直線過整數格點的情況,所以當然可以不止一個解,而擴展歐幾里得算法得到的只是其中一個。
首先從一個例子來感受一下該算法:
。
(a)方程系數(20, 12)變為(12, 8):
假設
,則變為:
(b)繼續將(12, 8)變為(8, 4):
假設
,則變為:
(c)繼續將(8, 4)變為(2, 0):
假設
,則變為:
(d)最后一個解(x3, y3)=(1, 0),那么從括號里的遞推公式,依次有:(x2, y2)=(0, 1),(x1, y1)=(1, -1),(x0, y0)=(-1, 2),最后一項即為原方程的一個解。
形如
的方程總是可以用(a)-(d)來求解。整個過程和輾轉相除類似(方程系數就是在做輾轉相除),而且如果方程有解(c%gcd(p,q)=0),那最后的解肯定是(c/gcd(p,q), 0),因為系數輾轉相除總是會到(gcd(p,q), 0)。其中變量轉換的遞推公式比較關鍵,但也很好理解,推廣一下就是(//和python的整數除法定義一致):
python實現代碼如下:這里先求解px+qy=gcd(p,q),再轉換為px+qy=c的解;這樣操作只是為了邏輯更清晰,實際上可以整合在一起(遞歸結束時返回值從(1, 0)變為(c/gcd(p,q), 0))px+qy=gcd(p,q)的解,求解過程不依賴于方程左邊的c;以(p,q)為遞歸過程,再反向遞歸求解(x,y)
test of integer_solution:實際上還有x=-2, y=2的解,多解的原因應該是前述(c)步驟中,最后一次變量轉換實際上可以不遵從遞推公式
從這個結果可知,如果想用3升和5升的水壺生成4升容積,解(8,-4)意味著總共會倒入8次3升水壺、倒掉4次5升水壺,而解(-2, 2)意味著總共會倒掉2次3升水壺、倒滿2次5升水壺。當然,解只是總體概括,至于具體步驟還需要進一步地分解了,不過問題就已經變得很簡單了。
4、本篇內容代碼的github鏈接gcd_euclidean_algorithm.py?github.com
總結
以上是生活随笔為你收集整理的python辗转相除_python(四):辗转相除的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件测试-测试计划
- 下一篇: websocket python爬虫_p