【问题标题】:python recursive function that prints from 0 to n?从0打印到n的python递归函数?
【发布时间】:2020-08-07 14:39:15
【问题描述】:

我正在尝试编写一个从0 打印到n 的递归函数,但我不知道该怎么做。我不小心做了一个从n 打印到0 虽然:

def countdown(n):
    print(n)
    if n == 0:
        return 0
    return countdown(n - 1)

我不知道这是否有帮助,也许我可以更改代码中的某些内容以使其从 0 变为 n

【问题讨论】:

    标签: python recursion


    【解决方案1】:

    你大约有 99% 在那里。

    想想你的基本情况和你的递归步骤 - 当你达到 0 时,你想做什么?当你还在努力从n 下来时,你想发生什么?

    如果你颠倒你打印值的顺序,你会得到你想要的结果。

    def countdown(n):
        if n != 0:
            countdown(n-1)
        print(n)
    

    这样做的原因是递归调用在调用堆栈上进行。当您将调用推送到堆栈上时,当您的最终情况未得到满足时,您将继续添加更多调用,直到达到基本情况 n == 0,然后您将专门开始打印值。

    然后其他调用将落入打印语句,因为它们的执行已返回到条件之后的行。

    所以,调用堆栈看起来像这样:

    countdown(5)
        countdown(4)
            countdown(3)
                countdown(2)
                    countdown(1)
                        countdown(0)
                        print(0)
                    print(1)
                print(2)
             print(3)
         print(4)
    print(5)
    

    【讨论】:

    • 确实如此。这将打印 0 1 2 3 4 5,全部在单独的行上。如果这是倒计时,它将在单独的行上打印 5 4 3 2 1 0。
    • 您的解决方案不需要 O(n) 内存。 @Andy Hayden 提供了一种在 O(1) 内存中执行此操作的方法(只需添加 tail_call 装饰器)。 Look at two pictures in SICP了解区别(你的答案是第一张图)
    • @J.F.Sebastian 我看不出安迪的解决方案如何使用更少的内存。两种解决方案都将使用n 堆栈帧,但安迪的每帧有两个局部变量,而这只有一个。
    • @Aya:注意:“添加 tail_call 装饰器”部分,here's an example。此外,对问题使用任何递归解决方案都是不切实际的,因此我认为 Python 在问题中用作可执行伪代码,即假设一些通用计算模型,其中函数调用不昂贵并且微不足道的尾调用消除可能存在。
    • @J.F.Sebastian +1 很有趣,但是如果你像那样破解堆栈,它在技术上不再是递归函数,至少在任何有意义的定义上是这样。因此,IMO,它与迭代解决方案一样有效:for i in xrange(10): print i 将使用更少的内存。关于实用性,您总是可以用堆栈递归代替堆递归,或者使用Stackless Python,但我同意在这种情况下递归是不合适的。然而,这纯粹是学术性的,而不是你在实践中做过的事情。
    【解决方案2】:

    你几乎明白了!这是一个固定的简化版本:

    def countup(n):
        if n >= 0:
            countup(n - 1)
            print(n)
    

    注意:

    • 您不必从只打印值的递归函数返回任何内容
    • 为了按升序打印,print 语句必须放在递归调用之后
    • 递归在n < 0时退出,鉴于我们只是打印,之后没有什么可做的,返回None(Python的默认返回值)就可以了

    更新

    似乎编写尾递归解决方案在这里风靡一时 :) 哦,好吧,这是我的尝试,@AndyHayden 想法的简化和尾递归版本 - 使用尾调用优化装饰器 recipe

    @tail_call_optimized
    def countup(N, n=0):
        print(n)
        if n < N:
            countup(N, n + 1)
    

    无论哪种方式,它都按预期工作:

    countup(5)
    => 0
       1
       2
       3
       4
       5
    

    【讨论】:

    • 不知道这个装饰器,太棒了!
    【解决方案3】:

    您可以将 0 和 n 以及 + 替换为 - 以使您的递归倒计时函数变为递归倒计时:

    def countup(N, n=0):
        print(n)
        if n == N:
            return
        return countup(N, n + 1)
    

    并调用如下:

    countup(3)
    

    @JFSebastian 指出这个算法的好处是 O(1) 而不是 O(n),正如 excellent article 中讨论的关于线性递归和迭代递归之间的区别,如果与 @ 一起使用987654325@装饰者。

    【讨论】:

    • OP 要求递归 UP 函数?没有?
    • 这个答案有效,但它确实违背了目的。您不需要从另一个参数开始(并且,如果我在 n 中输入 1,它不再从 0 打印到 n - 它从 n 打印到 N。跨度>
    • 不,它不是。如果我在n 中输入任何值,它现在会从n 绑定到N
    • 您是否...执行了该代码?输出实际上确实从 0 打印到 n
    • +1 这显示了使用递归进行迭代的正确方法。 @Makoto:the code does work: it print numbers in the range 0..n(含)
    【解决方案4】:

    你可以这样做

    def fun(num,n):
        if num<n:
            print(num)
            fun(num+1,n)
    n=int(input())
    print(fun(0,n+1)) 
    

    【讨论】:

      【解决方案5】:

      你也可以试试这个方法:

      def recursion_print(n):
          if n==0:
            print(n)
          else:
            recursion_print(n-1)
            print(n)
      
      
      recursion_print(9)
      

      【讨论】:

        猜你喜欢
        • 2021-12-09
        • 2020-02-26
        • 1970-01-01
        • 2015-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-18
        • 1970-01-01
        相关资源
        最近更新 更多