【问题标题】:Am I wrong to feel this recursive function feels like a 'for loop?' [closed]我觉得这个递归函数感觉像是一个“for循环”,我错了吗? [关闭]
【发布时间】:2013-07-16 13:30:17
【问题描述】:

有人能解释一下这个递归函数是如何产生 5 * 4 * 3 * 2 * 1 来得到 120 的吗?

var factorial = function(n){
   if (n === 0)
       return 1;
   else
       return n * factorial(n - 1); 
};

factorial(5); // spits out 120

如果我们像示例中那样使用 5,一旦我们到达 else 语句就不会

return n * factorial(n - 1);

翻译成'返回5乘以阶乘函数(5-1); 5次...

【问题讨论】:

  • 尝试在调试器中单步执行。
  • 不清楚你在问什么。你只是问递归是如何工作的?你最好看维基百科或教科书,而不是这个网站。
  • 如果你尝试factorial(-1),你会更好地意识到循环?
  • 我意识到我的回答从未真正回答过你标题中的问题,所以我更新了它。

标签: javascript loops recursion


【解决方案1】:

我觉得这个递归函数感觉像是一个“for循环”是不是错了?

不,递归和循环有很多共同点。特别是,它们都具有终止条件非常重要。 :-) 在这种情况下,终止条件是n === 0

理解这一点的最佳方法是在调试器中单步执行代码。您的浏览器有一个,因此您可以将该代码放在一个页面中并加载并浏览它。

让您开始:

  1. 你打电话给factorial(5)。因为n 不是=== 0,所以factorialn - 1 调用自己(4

  2. 现在我们已经递归了一层,我们正在运行factorial(4)(对factorial(5) 的调用仍未返回,它正在等待我们)。由于n 不是=== 0,我们调用factorial(3) 并等待 返回。

  3. ...冲洗,重复直到调用factorial(0)。由于n === 0 为真(此时,有五次对factorial 的调用未完成并堆积),factorial(0) 返回1,我们可以开始展开堆积的调用。

  4. 现在factorial(1) 可以通过将它从factorial(0) 得到的结果乘以它的n (1) 的副本并返回它来完成。

  5. ...让factorial(2) 完成并乘以2...

  6. ...冲洗重复...

或者用另一种方式显示嵌套(递归):

阶乘(5)
    返回 5 * 阶乘(4)
        返回 4 * 阶乘(3)
            返回 3 * 阶乘(2)
                返回 2 * 阶乘(1)
                    返回 1 * 阶乘(0)
                        返回 1

而且因为您无法获得足够的图表(或者至少无法获得):

阶乘(5) 阶乘(4) 阶乘(3) 阶乘(2) 阶乘(1) 阶乘(0)
    调用 ---------->
                    调用 ---------->
                                    调用 ---------->
                                                    调用 ---------->
                                                                    来电----------->
                                                                                     n 为 0,所以
                                                                                     返回 1
                                                                                             |
                                                                    返回 1 * 1


旁注:该函数不允许负数;它可能在一开始就使用警卫......

【讨论】:

  • 我喜欢嵌套,它真的很重要。你有没有找到其他答案?
【解决方案2】:

n 更改:

5 * factorial(5-1) = 5 * 4 * factorial(4-1) = 5 * 4 * 3 * factorial(3-1) = 5 * 4 * 3 * 2 * factorial(1-1) = 5 * 4 * 3 * 2 * 1

为了让这个函数更好,你可以在n等于1时停止它,因为1的阶乘是1:

var factorial = function(n){
   if (n === 1 || n === 0)
       return 1;
   else
       return n * factorial(n - 1); 
};

【讨论】:

    【解决方案3】:

    这个函数说:如果你想计算阶乘(5),好吧,那真的只是

    5 * factorial(4)
    

    如果你想计算阶乘(4),那真的只是 4 * 阶乘(3)

    5 * 4 * factorial(3)
    

    阶乘(3)实际上只是 3 * 阶乘(2)

    5 * 4 * 3 * factorial(2)
    

    等等。但是当你进入阶乘(0)时,函数最终停止(因为if n == 0 的情况)并返回1,没有任何进一步的递归。所以你得到

    5 * 4 * 3 * 2 * 1
    

    return n * factorial(n - 1) 转换为(在第一次运行时)“返回 (5 * 4!)”。它没有做任何事情 5 次。

    【讨论】:

      【解决方案4】:

      如果我们像示例中那样使用 5,一旦我们到达 else 语句就不会

      返回 n * 阶乘(n - 1);

      翻译成'返回5乘以阶乘函数(5-1); 5次...

      不,它会转换为“返回 n 乘以阶乘函数 (n-1)”(5 次,因为 n 从 5 开始,递减并进入 else 子句,直到达到 0)。

      1. 第一次输入函数时,n等于5。
      2. if 子句检查 n 是否等于 0。它不是,所以它转到:
      3. else 子句。这意味着“返回 5 乘以阶乘函数(您所在的函数)(5 - 1)。
      4. 当您输入阶乘函数时,n 现在是 4。

      重复所有这些步骤,直到 n 等于 0。然后 if 子句为真,函数将返回 1。

      所以 1 从阶乘(0)返回。 Factorial(1) 返回 1 * factorial(0),所以 1 * 1 = 1。

      Factorial(2) 返回 2 * factorial(1),所以 2 * 1 = 2。

      Factorial(3) 返回 3 * factorial(2),所以 3 * 2 = 6。

      Factorial(4) 返回 4 * factorial(3),所以 4 * 6 = 24。

      Factorial(5) 返回 5 * factorial(4),所以 5 * 24 = 120。

      【讨论】:

        猜你喜欢
        • 2012-01-15
        • 1970-01-01
        • 2010-10-11
        • 2020-02-25
        • 1970-01-01
        • 2021-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多