最大公約數的算法


算法的原理:

  對於輾轉相除法:i和j的最大公約數,也就是i和j都能夠除斷它。換句話講,就是i比j的n倍多的那個數k(i = j*n + k,即i % j = k)應該也是最大公約數的倍數。所以就能轉換成求k和j的最大公約數。同理,對於更相減損術,同樣的道理,i比j大的部分也是最大公約數的倍數。

 

代碼:

  

 1 /**
 2  * 求最大公約數算法匯總
 3  *
 4  */
 5 public class GCD {
 6     public static void main(String[] args) {
 7         GCD gcd = new GCD();
 8         gcd.gcd1(43, 45);
 9         gcd.gcd2(64, 80);
10         gcd.gcd3(45, 81);
11     }
12     
13     
14     /**
15      * 第三種方法:更相減損術 + 輾轉相除法,即
16      * 當a和b均為偶數,gcb(a,b) = 2*gcb(a/2, b/2) = 2*gcb(a>>1, b>>1)
17      * 當a為偶數,b為奇數,gcb(a,b) = gcb(a/2, b) = gcb(a>>1, b)
18      * 當a為奇數,b為偶數,gcb(a,b) = gcb(a, b/2) = gcb(a, b>>1)
19      * 當a和b均為奇數,利用更相減損術運算一次,gcb(a,b) = gcb(b, a-b), 此時a-b必然是偶數,又可以繼續進行移位運算。
20      */
21     private void gcd3(int i, int j) {
22         System.out.println("The greatest common divisor is:" + doubleGcd(i, j));
23     }
24     
25     private int doubleGcd(int i, int j) {
26         if (i % j == 0) {
27             return j;
28         } 
29         
30         if ((i&1) == 0 && (j&1) == 0) {
31             // 都是偶數
32             return doubleGcd(i >> 1, j >> 1) << 1;
33         } else if ((i&1) == 0 && (j&1) != 0) {
34             // i為偶數,j為奇數
35             return doubleGcd(i >> 1, j);
36         } else if ((i&1) != 0 && (j&1) == 0) {
37             // i為奇數,j為偶數
38             return doubleGcd(i, j >> 1);
39         } else {
40             // i和j都為奇數
41             return doubleGcd(i, i > j ? i - j : j - i);
42         }
43     }
44 
45 
46     /**
47      * 第二種方法:九章算術的更相減損術,即如果i>j,那么先用i-j得到其差k.然后將問題轉換成求k和m的最大公約數.依此類推,直到差為0.
48      * 這個方法也有一個問題,就是如果i和j想差的比較大,那么這個方法存在較高的時間復雜度.
49      */
50     private void gcd2(int i, int j) {
51         if (i < j) {
52             gcd2(j, i);
53             return;
54         }
55         
56         int k = i - j;
57         if (k == 0) {
58             System.out.println("The greatest common divisor is:" + j);
59             return;
60         } else {
61             if (k >= j) {
62                 gcd2(k, j);
63             } else {
64                 gcd2(j, k);
65             }
66         }
67     }
68 
69     /**
70      * 第一種方法:輾轉相除法, 即如果i>j, 那么先用i%j得到余數k.將問題轉換成求k和m的最大公約數.依此類推,直到余數為0.
71      * 該方法有一個比較大的問題問題是取模的性能。
72      */
73     private void gcd1(int i, int j) {
74         // 確保n>m
75         if (i < j) {
76             gcd1(j, i);
77             return;
78         }
79         
80         int k = i%j;
81         if (k == 0) {
82             System.out.println("The greatest common divisor is:" + j);
83             return;
84         } else {
85             if (k >= j) {
86                 gcd1(k, j);
87             } else {
88                 gcd1(j, k);
89             }
90         }
91     }
92 }    
GCD

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM