快速求得a和b的最大公约数的主要方式有两种:
- 更相减损法
- 欧几里得算法
其中欧几里得算法的递归实现最为好写,复杂度为O(log(a+b)),在绝大多数的情况下适用,只有在需要实现高精度时,才会考虑使用更相减损法。
还有一种stein算法,三叶大佬说是没有必要掌握的。
以今天的LeetCode每日一题(1447. 最简分数)为例:
class Solution {
//欧几里得算法(又叫辗转相除法)
int gcd(int a, int b) {
return b == 0? a : gcd(b, a % b);
}
public List<String> simplifiedFractions(int n) {
List<String> res = new ArrayList<>();
for (int i = 1; i < n; i++) {
for (int j = i + 1; j <= n; j++) {
if (gcd(i, j) == 1) res.add(i + "/" + j);
}
}
return res;
}
}
/**
*更相减损法
*/
int gcd(int a, int b) {
while (true) {
if (a > b) a -= b;
else if (a < b) b -= a;
else return a;
}
}
- 欧几里得算法的结论:gcd(a, b) = gcd(b, a mod b),证明过程可bilibili;递归写法就是反复利用这个结论,直到出现可以整除的两数,较小的数即为两者的最小公约数。
- 更相减损法更容易从名字上直观地理解,每次都是大数减小数,直到两数相同为止,此时的数值即为所求的最小公约数。