递归没有破坏

时间:2014-07-27 12:54:35

标签: python recursion

我正在尝试解决欧拉问题18,我需要从上到下找出最大总数。我试图使用递归,但我坚持这个。

我想我之前没有提出我的问题。我试图通过递归实现的是找到最大数量路径的总和。我从三角形的顶部开始,然后检查条件是7 + findsum()更大或4 + findsum()更大。 findsum()应该找到它下面的数字之和。我将总和存储在变量'结果' 问题是我不知道这个递归函数的破坏情况。我知道当它到达子元素时它应该会中断,但我不知道如何在程序中编写这个逻辑。

pyramid=[[0,0,0,3,0,0,0,],
         [0,0,7,0,4,0,0],
         [0,2,0,4,0,6,0],
         [8,0,5,0,9,0,3]]

pos=[0,3]

def downleft(pyramid,pos):#returns down left child
    try:
        return(pyramid[pos[0]+1][pos[1]-1])
    except:return(0)    

def downright(pyramid,pos):#returns down right child
    try:
        return(pyramid[pos[0]+1][pos[1]+1])
    except:
        return(0)   

result=0

def find_max(pyramid,pos):

    global result

    if downleft(pyramid,pos)+find_max(pyramid,[pos[0]+1,pos[1]-1]) > downright(pyramid,pos)+find_max(pyramid,[pos[0]+1,pos[1]+1]):
        new_pos=[pos[0]+1,pos[1]-1]
        result+=downleft(pyramid,pos)+find_max(pyramid,[pos[0]+1,pos[1]-1]) 

    elif downright(pyramid,pos)+find_max(pyramid,[pos[0]+1,pos[1]+1]) > downleft(pyramid,pos)+find_max(pyramid,[pos[0]+1,pos[1]-1]):
        new_pos=[pos[0]+1,pos[1]+1]
        result+=downright(pyramid,pos)+find_max(pyramid,[pos[0]+1,pos[1]+1])

    else :
        return(result)  

find_max(pyramid,pos)

2 个答案:

答案 0 :(得分:1)

编辑:我发现你在使用代码逻辑时遇到了麻烦。那么让我们来看看。

  1. 在树中的每个位置,您都可以选择选择 来自的路径具有最高值。所以呢 你做的是,你计算左路的得分和得分 正确的道路。我看到这是你在当前代码中尝试的东西, 只有一些效率低下的问题。你计算一切 两次(首先在if,然后在elif),这非常昂贵。你应该只计算一次孩子的价值。
  2. 你要求停止条件。好吧,如果你到达树的底部,从这一点开始的路径得分是多少?这只是树中的价值。那就是你应该在那时回归。
  3. 所以结构应该是这样的:

    function getScoreAt(x, y):
       if at the end: return valueInTree(x, y)
    
       valueLeft = getScoreAt(x - 1, y + 1)
       valueRight = getScoreAt(x + 1, y + 1)
       valueHere = min(valueLeft, valueRight) + valueInTree(x, y)
       return valueHere
    

    额外提示: 你是否意识到在Python中,负面索引会回绕到数组的后面?因此,如果您执行pyramid[pos[0]+1][pos[1]-1],您实际上可能会遇到pyramid[1][-1]这样的元素,它位于金字塔行的另一侧。您可能期望的是,这会引发错误,但事实并非如此。

    要解决您的问题,您应该添加显式绑定检查,而不是依赖try块(try块,因为这也不是一个很好的编程风格。)

答案 1 :(得分:1)

您的问题很大一部分就是您需要更多地递归 。你应该只是递归地调用find_max两次,并且你需要一些基本逻辑来在最后一行之后停止。

试试这段代码:

def find_max(pyramid, x, y):
    if y >= len(pyramid):   # base case, we're off the bottom of the pyramid
        return 0            # so, return 0 immediately, without recursing

    left_value = find_max(pyramid, x - 1, y + 1)     # first recursive call
    right_value = find_max(pyramid, x + 1, y + 1)    # second recursive call

    if left_value > right_value:
        return left_value + pyramid[y][x]
    else:
        return right_value + pyramid[y][x]

我更改了调用签名,使其具有单独的坐标值,而不是使用元组,因为这使得索引更容易编写。使用find_max(pyramid, 3, 0)调用它,并删除全局pos列表。我也摆脱了result全局(函数返回结果)。

这种算法可以从记忆中受益匪浅,因为在更大的金字塔上,你可以多次计算中下区域的值。如果没有memoization,对于大金字塔大小,代码可能会非常慢。