编程思考挑战

探索编程的深度,挑战思维的边界。翻转卡片查看问题,思考解决方案,然后查看我们的分析。

初级

递归的奥秘

考虑以下递归函数:

function mystery(n) {
    if (n <= 1) return 1;
    return n * mystery(n - 1);
}

当调用 mystery(5) 时,返回值是多少?

解析

这是一个经典的阶乘函数实现。

递归过程:

  • mystery(5) = 5 * mystery(4)
  • mystery(4) = 4 * mystery(3)
  • mystery(3) = 3 * mystery(2)
  • mystery(2) = 2 * mystery(1)
  • mystery(1) = 1

因此,mystery(5) = 5 * 4 * 3 * 2 * 1 = 120

时间复杂度:O(n)

中级

闭包陷阱

以下代码的输出是什么?

for (var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 100);
}

如何修改代码使其输出 0,1,2,3,4?

解析

输出是五个 5,而不是预期的 0 到 4。

原因:

  • setTimeout 是异步的,循环结束后才执行
  • var 没有块级作用域,所有回调共享同一个 i
  • 循环结束时 i 的值是 5

解决方案:

  1. 使用 let 声明 i(块级作用域)
  2. 使用闭包创建新作用域
  3. 使用立即执行函数(IIFE)
// 使用 let
for (let i = 0; i < 5; i++) {
    setTimeout(() => console.log(i), 100);
}
高级

算法优化

实现一个函数,判断一个数是否为质数:

function isPrime(n) {
    // 你的实现
}

要求:

  • 时间复杂度低于 O(n)
  • 正确处理边界情况(n ≤ 1)
  • 尽可能优化性能

解析

优化思路:

  • 排除 ≤1 的情况
  • 检查 2 和 3 的特殊情况
  • 只需检查到 sqrt(n)
  • 跳过偶数(除2外)

优化实现:

function isPrime(n) {
    if (n <= 1) return false;
    if (n <= 3) return true;
    if (n % 2 === 0 || n % 3 === 0) return false;
    
    for (let i = 5; i * i <= n; i += 6) {
        if (n % i === 0 || n % (i + 2) === 0) 
            return false;
    }
    return true;
}

时间复杂度:O(√n)