如何重新实现这个递归函数?

时间:2015-11-29 18:34:48

标签: python recursion

所以我试图解决一个难题,我遇到了这个代码。我无法弄清楚输出是什么,任何运行它的尝试都会导致“达到最大递归量”错误。提前抱歉愚蠢的变量名称。

如何在没有递归错误的情况下修改它以实现相同的输出?我通过的初始数字是13379446(arg 1)和5(arg 2)。

import sys

num1 = int(sys.argv[1])
num2 = int(sys.argv[2])

def doot(num1, num2):
    print num1
    print num2
    doritos = 0
    if num2 > num1:
        pass
    else:
        if num2 == 0:
            print "if"
            doritos = 1
        else:
            if num2 == num1:
                doritos = 1 
            else:
                wew = doot(num1 - 1, num2 - 1)
                doritos = wew
                wew = doot(num1 -1, num2)
                doritos = doritos + wew

    print doritos

3 个答案:

答案 0 :(得分:2)

让我帮你。我假设doritos应该是返回值,也就是代码应该说return dortitos而不是print doritos。另外,我完全忽略了行print if

现在我们知道什么?看看我们看到的代码

doot(x,y) = 0 if y > x
doot(x,0) = 1
doot(x,x) = 1 and
doot(x,y) = doot(x-1,y-1) + doot(x-1,y) otherwise 

所以我们想弄清楚doot(x + h,x)的值,其中h> 0.从最简单的情况开始,h = 1。我们已经知道doot(1,0)= 1,所以

doot(2,1) = doot(1,0)+doot(1,1) = 1+1 = 2
doot(3,2) = doot(2,1)+doot(2,2) = 2+1 = 3

现在很容易猜到

doot(x+1,x)=x+1 for all x>= 0. 
如果你愿意的话,通过归纳也很容易证明这一点。

现在,在h = 2时计算出一些例子,并找出doot(x + 2,x)的公式。然后找出doot(x + 3,x)等的公式,直到你准备好猜测doot的公式(x + h,x)

答案 1 :(得分:1)

好的,我对您的代码进行了大修,以使用字典(values)和队列。

import sys

num1 = int(raw_input("num1: "))
num2 = int(raw_input("num2: "))

def doot(num1, num2):
    print num1
    print num2
    doritos = 0
    n1 = num1
    n2 = num2

    values = {}
    queue = [(num1,num2)]

    while queue:
        num1,num2 = queue.pop()
        #print queue
        #print values

        if (num1,num2) not in values:
            if num1 >= num2:
                if num2 == 0:
                    #print "if"
                    #doritos = 1
                    values[(num1,num2)] = 1
                else:
                    if num2 == num1:
                        #doritos = 1
                        values[(num1,num2)] = 1
                    else:
                        #wew = doot(num1 - 1, num2 - 1)
                        #doritos = wew
                        #wew = doot(num1 -1, num2)
                        #doritos = doritos + wew

                        if (num1-1,num2-1) in values and (num1-1,num2) in values:
                            values[(num1,num2)] = values[(num1-1,num2-1)] + values[(num1-1,num2)]
                        else:
                            queue.append((num1,num2))

                        if (num1-1,num2) not in values:
                            queue.append((num1-1,num2))

                        if (num1-1,num2-1) not in values:
                            queue.append((num1-1,num2-1))

    #print values

    doritos = values[(n1,n2)]

    print doritos
    return doritos

doot(num1,num2)

本质上,我使用队列来跟踪我还没有的总和。如果(num1,num2)的两个后代都在字典中,那么我将它与它们的值之和放在字典中。否则,我将其中一个或两个不在字典中的后代与其自身放在一起。我没有将(num1,num2)放回队列的其他时间是num1 == num2num2 == 0,在这种情况下我将它们放在值为1的字典中。最后,我返回字典中与原始输入数字对应的值。

现在,提醒一句:这段代码非常低效。我只需要重新启动计算机,因为我尝试了你在问题中提供的输入,并且它吞噬了所有可用的RAM 。因此,您应该考虑使用递归完成的内容,并找出如何从基本案例中而不是从输入向后工作转发。那项任务,我会留给你。

答案 2 :(得分:1)

您的代码是combination函数的递归实现,它计算可以从一组n个元素中提取的k个不同元素的组合数。

你的函数的整理版本看起来像这样(注意我删除了所有的打印语句,并确保函数返回一些东西 - 否则它根本不会起作用。)

def doot(n, k):
    if n < k:
        return 0
    if k == 0 or n == k:
        return 1
    return doot(n - 1, k - 1) + doot(n - 1, k) 

这适用于nk的小值。不依赖于递归的更快版本使用阶乘,如this answer所示。

import math

def nCr(n, r):
    f = math.factorial
    return f(n) / f(r) / f(n - r)

然而,计算阶乘13379446仍然需要很长时间,可能不准确,因为结果是如此巨大。我尝试时系统挂起。 The other answer对同一问题似乎更有效。