【问题标题】:Rewrite the recursive function into tail recursive function将递归函数重写为尾递归函数
【发布时间】:2020-09-16 23:33:49
【问题描述】:

问题:通过掷骰子一次或多次来计算构造 sum n 的方法的数量。每次投掷都会产生 1 到 6 之间的结果。

解决方案:我已经为它编写了一个递归解决方案,它输出正确的答案。对于较大的 n 值,它应该会发生堆栈溢出。所以我想避免它并使用尾递归方法重写代码。这是我的代码:

def numWays(n, arr):
  answer = 0
  for item in arr:
    if item <= n:
      if n == item:
        answer += 1
      else:
        answer += numWays(n-item, arr)

  return answer

li = [i for i in range(1,7)]
print(numWays(5, li)) #example n=5

我在 web 上看到了将阶乘函数编写为尾递归的示例,但这很容易。无法应用该累加器技巧将所需答案存储为函数调用中的附加参数。有没有其他通用的技巧?

这也可以重写为迭代函数,但我正在寻找将递归函数转换为尾递归的一般方法。给定的问题、代码和 Python 仅作为示例。没有什么具体的。

【问题讨论】:

  • 你有没有看过这个post,为什么尾递归在 python 中并不重要,以及设置最大递归级别的方法?
  • @BalajiAmbresh:实际上我的重点是将递归重写为尾递归。我最初是用 Scala 编写的,但 Python 更为人所知,所以在这里以它为例。
  • 你能解释一下“构造和 n 的方法”是什么意思吗?特别是“总和”
  • @ePi272314:比如n=3,有4种方式:a)1+1+1 b)1+2 c)2+1 d)3

标签: python algorithm recursion stack-overflow tail-recursion


【解决方案1】:

解决堆栈溢出问题的一种方法是手动模拟调用堆栈。

def numWays(n, arr):
    call_stack = [(n, arr)]
    answer = 0
    while call_stack:
        n, arr = call_stack.pop(0)
        for item in arr:
            if item <= n:
                if n == item:
                    answer += 1
                else:
                    call_stack.insert(0, (n-item, arr))
    return answer


li = [i for i in range(1, 7)]
print(numWays(5, li))

输出:

16

【讨论】:

    【解决方案2】:

    这是一个简单的解决方案,没有递归,没有什么,O(N):

    #!/usr/bin/env python
    
    DICE = 6    # how many sides our dice has
    
    rolls = [1]
    for i in range(1,800) :
        rolls.append(sum(rolls[-min(i,DICE):]))
    
    print rolls[:16]  # print results for the first 16 (zero-based!!)
    print rolls[610]  # print result for 610 steps
    

    结果:

    [1, 1, 2, 4, 8, 16, 32, 63, 125, 248, 492, 976, 1936, 3840, 7617, 15109]
    14527490260516100855695859704819627818108010882741117227956927412305738742399171256642436462028811566617818991926058940988565927870172608545709804976244851391054850231415387973537361
    

    可以轻松计算 N=50000 或 500000 的卷数。

    【讨论】:

    • 谢谢。但我实际上想学习如何将递归函数更改为一般的尾递归。仅以问题、代码和 Python 为例,这样问题就不会变得过于理论化。也许我应该特别提到这个问题。
    猜你喜欢
    • 1970-01-01
    • 2019-09-14
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    相关资源
    最近更新 更多