讀書筆記——漫畫算法(4) 最大公約數

求最大公約數的若干個方法:

  • 暴力枚舉
  • 輾轉相除法(歐幾里得算法)
  • 更相減損法(九章算術)
  • 上兩種方法的結合優化版本
public class GCD {

    /**
     * 2 * x == k, 或者 2 * x + 1 == k
     * 既然要求最大公約數,我們就從最大的數開始,
     * 那麼就如上面所示,最先從x開始考慮
     * @param a
     * @param b
     * @return
     */
    public static int gcd(int a, int b) {
        int big = Math.max(a, b);
        int small = Math.min(a, b);
        if(big % small == 0) {
            return small;
        }
        for(int i = small >> 1 ; i > 1 ; i--) {
            if(small % i == 0 && big % i == 0) {
                return i;
            }
        }
        return 1;
    }

    /**
     * 輾轉相除法(歐幾里得算法)
     *
     * 如果算法入口處 a < b,例如 5, 25
     * 則這個算法會自動將5,25進行交換
     * gcd1(5, 25) = gcd1(25, 5 % 25) = gcd1(25, 5)
     *
     * 而總是有b > a % b,所以這個算法總能夠保證 a >= b
     * @param a
     * @param b
     * @return
     */
    public static int gcd1(int a, int b) {
        return b == 0 ? a : gcd1(b, a % b);
    }

    /**
     * 更相減損法
     * @param a
     * @param b
     * @return
     */
    public static int gcd2(int a, int b) {
        if(a == b) {
            return a;
        }
        int big = Math.max(a, b);
        int small = Math.min(a, b);
        return gcd2(big-small, small);
    }

    /**
     * a, b均爲偶數,    則 gcd(a, b) = 2 * gcd(a/2, b/2) = gcd(a >> 1, b >> 1) << 1;
     * a爲奇數,b爲偶數,則 gcd(a, b) = gcd(a, b >> 1)
     * a爲偶數,b爲奇數  則 gcd(a, b) = gcd(a >> 1, b)
     * a,b均爲奇數,    則 gcd(a, b) = gcd(a - b, b)   {假設a >= b}
     * @param a
     * @param b
     * @return
     */
    public static int gcd3(int a, int b) {
        if(a == b) {
            return a;
        }
        if((a & 1) == 0 && (b & 1) == 0) {
            return gcd3(a >> 1, b >> 1) << 1;
        } else if((a & 1) == 0 && (b & 1) != 0) {
            return gcd3(a >> 1, b);
        } else if((a & 1) != 0 && (b & 1) == 0) {
            return gcd3(a, b >> 1);
        } else {
            int big = Math.max(a, b);
            int small = Math.min(a, b);
            return gcd3(big-small, small);
        }
    }

    public static void main(String[] args) {
        System.out.print(gcd(25, 5) + " ");
        System.out.print(gcd(100, 80) + " ");
        System.out.println(gcd(27, 14));

        //
        System.out.print(gcd1(25, 5) + " ");
        System.out.print(gcd1(100, 80) + " ");
        System.out.println(gcd1(27, 14));

        //
        System.out.print(gcd2(25, 5) + " ");
        System.out.print(gcd2(100, 80) + " ");
        System.out.println(gcd2(27, 14));

        //
        System.out.print(gcd3(25, 5) + " ");
        System.out.print(gcd3(100, 80) + " ");
        System.out.println(gcd3(27, 14));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章