• 求最大公约数的两种方法


    辗转相除法(欧几里得算法)

    欧几里德算法又称辗转相除法,是指用于计算两个正整数a,b的最大公约数。
    时间复杂度为(O(logN))

    举例

    比如:30和42的最大公约数:
    (30 mod 42 = 30)
    (42 mod 30 = 12)
    (30 mod 12 = 6)
    (12 mod 6 = 0)
    那么,30和42的最大公约数就是6。

    代码实现

    int gcd(int a, int b) {
        while (b > 0) {
            c = a % b;
            a = b;
            b = c;
        }
        return a;
    }
    

    我们也可以使用递归的方法来实现。

    int gcd(int a, int b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }
    

    性能分析

    由于辗转相除法的时间复杂度为(O(logN)),在遇到比较大的数时((Nge{10^{256}})),计算起来就会比较慢了。
    这是因为辗转相除法中含有模运算,当(amod{b})时,相当于(a)减了(k)(b),也就是(a - k * b)
    比如:
    (42 mod 30 = 42 - 1 * 30)
    (30 mod 12 = 30 - 2 * 12)

    更相减损术

    更相减损术是出自《九章算术》的一种求最大公约数的算法,它原本是为约分而设计的,但它适用于任何需要求最大公约数的场合。
    最坏时间复杂度为(O(N))

    举例

    (a>b)时,用(a-b);当(b>a)时,用(b-a)
    (gcd(30, 42) = gcd(12, 30) = gcd(18, 12) = gcd(6, 12) = gcd(6, 6))
    (a=b)时,(a)就是这两个数的最大公约数。

    代码实现

    int gcd(int a, int b) {
        if (a == b) return a;
        else if (a > b) return gcd(a - b, b);
        else if (a < b) return gcd(b - a, a);
    }
    

    更相减损术二分版

    上文提到,在两个差距非常大的数((a=10000, b=1)),使用更相减损术的时间复杂度为(O(N))
    这个算法的时间复杂度为(O(logN))

    代码实现

    可以使用按位与(&)来代替模运算。
    例如:((5)_{10} = (101)_{2}),我们可以使用5&1来达到和模运算符一样的效果。
    我们知道,按位左移1位就是乘2,右移一位就是除以2。

    int gcd(int a, int b) {
        if (a == b) return a;
        if ((a & 1) && (b & 1)) return gcd(a >> 1, b >> 1) << 2; // a和b都是偶数
        else if ((a & 1) && !(b & 1)) return gcd(a >> 1, b); // a是偶数b是奇数
        else if (!(a & 1) && (b & 1)) return gcd(a, b >> 1); // a是奇数b是偶数
        else if (!(a & 1) && !(b & 1)) { // a和b都是奇数
            if (a > b) return gcd(a - b, b);
            else if (a < b) return gcd(b - a, a);
        }
    }
    

    参考

    感谢Vita小老师~
    【算法小知识】如何求最大公约数(上)
    【算法小知识】如何求最大公约数(下)

  • 相关阅读:
    [leetcode]397. Integer Replacement
    [LeetCode]396. Rotate Function
    [leetcode]633. Sum of Square Numbers
    [LeetCode]367. Valid Perfect Square判断完全平方数
    [LeetCode]319. Bulb Switcher灯泡开关
    [LeetCode]313. Super Ugly Number超级丑数,丑数系列看这一道就行了
    [LeetCode]231. Power of Two判断是不是234的幂
    使用导入外部样式文件方式
    使用内部样式
    使用链接外部样式文件方式
  • 原文地址:https://www.cnblogs.com/luoling8192/p/12859468.html
Copyright © 2020-2023  润新知