zoukankan      html  css  js  c++  java
  • 最大公约数的算法

    算法的原理:

      对于辗转相除法: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
  • 相关阅读:
    后缀数组
    网络流 HOJ1087
    备用
    css-具有缩略图的材料列表
    正则匹配log行
    vue-cli的webpack打包,icon无法正确加载
    导出CSV,导出excel数字过长显示科学计数法解决方案
    js导出CSV
    git常见操作指令
    javascript原型的意义
  • 原文地址:https://www.cnblogs.com/Kidezyq/p/5974718.html
Copyright © 2011-2022 走看看