public static int math(int a, int b) {
...
}
分析: 關於這道題的算法有多種,我們今天只研究下面這種算法:
1 public static int math(int a, int b) {
2 int hold = 0;
3 while (b != 0) {
4 hold = a % b;
5 a = b;
6 b = hold;
7 }
8 return a;
9 }
初看這個解法,你可能會一頭霧水。再看看,更是不知所云。甚至懷疑這樣算是不是可 以得到正確結果,但經過測試你會發現的確可以得到正確結果,這究竟是爲什麼呢?讓我們 來分析一下這個算法,爲了便於敘述,把行號加上:
第 1 行,程序調用這個方法時會傳入兩個正整數 a 和 b
第 2 行,聲明一個 int 類型的變量 hold 並賦初值 0;第 3-7 行是一個 while 循環,循環條件是 b!=0;
第 4 行,用 hold 來保存 a%b 的結果
第 5 行,把 b 的值賦給 a
第 6 行,把 hold 的值賦給 b
若 b 不爲 0,則進行下一次循環,直到 b=0 時停止循環
最後第 8 行把 a 的值返回。
首先我們假設程序只進行一次循環,也就是說:方法傳入 a 和 b 時
第 4 行,hold=a%b=0;
第 5 行,a=b;
第 6 行,b=hold=0;再進行第 3 行判斷循環停止
第 8 行,返回 a 的值,也就是第 5 行中方法開始時傳入的 b 的值,這說明: 如果 a%b=0 那麼 a 和 b 的最大公約數就爲 b,
這點好理解,a%b=0 也就是說 a 能被 b 整除,那當然 a 和 b 的最大公約數就是 b 了。 關鍵是如果不是進行一次,而是進行多次循環呢?
爲了便與理解,我把上面的程序改爲遞歸算法:
1 public static int math1(int a, int b) {
2 if (b == 0) {
3 return a;
4 }
5 int hold = a % b;
6 a = b;
7 b = hold;
8 return math1(a, b);
9 }
第 1 行,程序調用這個方法時傳入兩個正整數 a 和 b
第 2-4 行,如果 b 等於 0 返回 a 的值
第 5 行,聲明一個 int 類型的變量 hold 保存 a%b 的結果
第 6 行,把 b 的值賦給 a
第 7 行,把 hold 的值賦給 b
第 8 行,遞歸調用,直到 b 的值爲 0 時返回 a 的值
最後第 8 行把 a 的值返回。
在首次調用這個方法傳入 a 和 b 的值時第 3 行肯定不會執行,而是執行 5-8 行的代碼, 由第 8行,我們可以看出程序的意思是 a和 b的最大公約數與 b和 a%b 的最大公約數相同。
假設程序進行三次遞歸: |
|
|
第一次程序傳入 a 和 b, |
35 |
30 |
第二次相當於傳入 b 和 a%b, |
30 |
5 |
第三次相當於傳入 a%b 和 0;(上次中 b%(a%b)=0) |
5 |
0 |
最後程序返回 a%b。 |
5 |
|
由此我們可以得到如下兩個命題:
命題一:a 和 b 的最大公約數與 b 和 a%b 的最大公約數相同;
命題二:如果 b%(a%b)=0,那麼 a 和 b 的最大公約數爲 a%b,(其中 a,b 都爲正整數,且 a%b!=0)。
如果能證明這兩個命題,則上面的算法也就不難理解了:因爲程序實際上一直在運用命題一反覆進行遞歸調用,只是在最後兩次時運用命題二,得出最後結果。
我們先看命題一:a 和 b 的最大公約數與 b 和 a%b 的最大公約數相同。 證明:由於 a%b!=0 則 a!=b,當 a<b 時 a%b=a,命題自然成立;
當 a>b 時可設 a 和 b 的最大公約數爲 x;
a=mx,b=nx,其中 m 和 n 爲正整數且 m 與 n 互質(除 1 之外再無其它公因數) 則可設:a%b=(m-kn)x,其中 k 爲正整數
這說明:b 和 a%b 有公因數 x,下面證明 n 與 m-kn 互質 假設 n 與 m-kn 有公因數 y,y 爲正整數且 y 不等於 1 則可設:n=py,m-kn=qy,其中 p 和 q 爲正整數 那麼:m-kn=m-kpy=qy
可得:m=kpy+qy=(kp+q)y
這說明 m 和 n 有公因數 y,與 m 和 n 互質相矛盾,故 n 與 m-kn 互質 由此得 b 和 a%b 的最大公約數也爲x,命題一得證。
再看命題二:如果 b%(a%b)=0,那麼 a 和 b 的最大公約數爲 a%b
爲了便於證明我們修改一下這個命題:
已知:m 爲正整數,a=mb+x(即 a%b=x),b 能被 x 整除(即 b%x=b%(a%b)=0),
求證:a 和 b 的最大公約數爲 x(即 a%b) 證明:因爲 b 能被 x 整除,故可設
b=nx,(其中 n 爲正整數)
則:
a=mb+x
=mnx+x
=(mn+1)x
所以:
a 也能被 x 整除 那麼:
a 和 b 的最大公約數一定是 x 的倍數,假設爲 kx,其中 k 爲正整數 則可設:
a=pkx,b=qkx,其中 p 和 q 都爲正整數
那麼:
a=mb+x
=mqkx+x
=(mqk+1)x=pkx
故:
mqk+1=pk
解出 k 得:
k=1/(p-mq)
由於:其中 m、p、q、k 都爲正整數故:k 的值只能爲 1
所以:a 和 b 的最大公約數爲 x,命題二得證。
至此問題得以解決。