Digital Garden

辗转相除法:古老而优雅的数学之美

🌱 Seedling算法数学递归基础

核心逻辑:gcd(a, b) = gcd(b, a % b)。它是解决最大公约数(GCD)和最小公倍数(LCM)问题的终极武器。

辗转相除法(欧几里得算法)不仅是求最大公约数(GCD)的工具,更是理解“递归”和“分治”思想的入门砖。

1. 核心逻辑:一句话记忆

“大数除以小数,取余代大数,直到余数为零。”

其数学表达式极为简洁:gcd(a, b) = gcd(b, a % b)。当 b 变为 0 时,剩下的 a 就是我们要找的那个最大的“公约数”。

2. 为什么我们要背下这个模板?

在 LeetCode 中,它往往不是题目的全部,而是某个复杂逻辑的一环。如果你能闭着眼写出 GCD,你就能快速解决:

  • 🎯 [LeetCode 149. 直线上最多的点数]:需要用 GCD 来化简斜率。
  • 🎯 [LeetCode 365. 水壶问题]:著名的裴蜀定理应用,本质就是看目标水量是否是 GCD 的倍数。
  • 🎯 [最小公倍数 LCM]:有一个核心公式必背:LCM(a, b) = (a * b) / GCD(a, b)

3. 标准代码模板(递归 vs 迭代)

我个人更推荐递归版,因为它完美契合数学定义,且代码极其短小:

/**
 * 求最大公约数 (Greatest Common Divisor)
 */
function gcd(a, b) {
    // 递归基准条件:当余数为 0 时,b 为 0,此时 a 就是最大公约数
    return b === 0 ? a : gcd(b, a % b);
}

// 迭代版(如果你担心递归栈溢出,虽然 GCD 极少发生)
function gcdIterative(a, b) {
    while (b !== 0) {
        let temp = a % b;
        a = b;
        b = temp;
    }
    return a;
}

4. 应用场景与“心法”

  • 化简分数:分子分母同时除以 gcd(numerator, denominator)
  • 平铺问题:用正方形地砖铺满长方形地面,正方形的最大边长就是长宽的 GCD。
  • 周期同步:两个不同周期的闹钟同时响起,下一次同时响起的间隔就是它们的 LCM(由 GCD 求得)。

锻造感悟: 辗转相除法展示了算法中最迷人的一面——收敛性。无论输入的数字多大,取余操作都会让规模以惊人的速度缩小。这提醒我,面对复杂问题,通过不断的“取余(去除冗余,聚焦核心)”,终能看到问题的本原。