【问题标题】:Understanding factorial recursion [duplicate]了解阶乘递归
【发布时间】:2014-04-23 18:45:21
【问题描述】:

我正在查看递归的阶乘示例,并希望确保我正确理解它!

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)

我说得对吗:

阶乘(4) = 阶乘(4-1) * 4 = 阶乘(3-1) *3 *4 = 阶乘(2-1) *2 *3 *4 = 阶乘(1-1) *1 * 2 *3 *4 = 24

因为 factorial(1-1) = factorial(0) 作为基本情况显示 = 1,然后我们乘以 2,然后是 3,然后是 4。

这是正确的看待它的方式吗?

提前致谢!

【问题讨论】:

  • 确实是正确的思考方式。
  • 查看递归的正确方法,但您假设乘法是可交换的。应该是4*3*2*1*factorial(1-1) 甚至是4*(3*(2*(1*factorial(1-1))))

标签: python recursion factorial


【解决方案1】:

是的。但由于它是递归的,所以它的工作方式相反。我曾经有一个面试官这样向我解释过:

说,事实(5):

 - fact(5) = 5 * fact(4)
           - fact(4) = 4 * fact(3)
                     - fact(3) = 3 * fact(2)   
                               - fact(2) = 2 * fact(1)
                                         - fact(1) = 1 * fact(0) 
                                                   - fact(0) = 1
                                                   // This is where your condition returns 1.

现在,想象一下上面的- 符号代表返回。您基本上返回 - 符号之后的任何内容。因此,从最低行开始,返回 1。然后,您实际上返回了 1(1),即 1 * 1。所以它发生在 REVERSE 级联中,例如:

 = 120
 - fact(5) = 5 * 24
           - fact(4) = 4 * 6 = 24
                     - fact(3) = 3 * 2 = 6  
                               - fact(2) = 2 * 1 = 2
                                         - fact(1) = 1 * 1 = 1
                                                   - fact(0) = 1

请记住,每当您使用递归时,实际上一切都是相反的。这应该真的可以帮助您解决任何递归问题。

这就是为什么尾递归和相关优化如此重要的原因。在内存中,这些调用中的每一个都被延迟并且不能返回,直到它上面的调用(在图中的下方)完成并返回。所以一个非常深的递归调用可能会导致堆栈溢出,除非编译器/解释器通过将其转换为 OP 中的版本来优化它,以便立即评估部分结果而不是延迟。 Python 不执行此优化,因此您必须小心递归调用。

【讨论】:

    【解决方案2】:

    这可能会有所帮助

    (factorial 4)
    (4 * (factorial 3))
    (4 * (3 * (factorial 3)))
    (4 * (3 * (2 * (factorial 1))))
    (4 * (3 * (2 * 1)))
    (4 * (3 * 2))
    (4 * 6)
    (24)
    

    【讨论】:

      【解决方案3】:

      是的,您描述的方式就是正在发生的事情。

      在您的代码中要注意一点,如果您为n 输入一个非整数值或n 小于0 的值,看起来您将陷入无限循环。

      可能值得在您的代码中添加一个检查:

      if not isinstance(n, int): 
            return None
      
       elif n < 0: 
            return None
      

      【讨论】:

        猜你喜欢
        • 2017-03-17
        • 1970-01-01
        • 2013-10-13
        • 2016-01-28
        • 1970-01-01
        • 2015-04-19
        • 2019-08-06
        • 2019-07-24
        • 1970-01-01
        相关资源
        最近更新 更多