如何使递归解决方案返回所有可能的解决方案?

时间:2021-02-10 15:50:15

标签: python recursion

对于这个递归函数,当你输入一个列表如[2,8,3,2,7,2,2,3,2,1,3,0]时,它会找到从第一个索引到包含值0的索引的路径,但只能在列表中移动{{1} } 或 index[i]+i 并且不能越过列表的边界或转到已经访问过的索引。

因此,如果您在 index[i]-i 等于 2,则只能在列表中向前移动 2。或者,如果您在 index[0],则只能在列表中向前或向后移动按 2 列出;所以你可以去index[3]index[1]

对于列表index[5],我得到的解决方案是[2,8,3,2,7,2,2,3,2,1,3,0],但是还有更多的解决方案,例如[0,2,5,7,4,11],我不知道如何让我的函数继续搜索对于所有其他人。

1 个答案:

答案 0 :(得分:0)

携带包含所有解决方案的第二个列表(列表),例如

def findAllPaths(vector, position, solution, all_solutions):
    if position not in solution and position >= 0 and position < len(vector):
        solution = solution + [position] 
        if vector[position] == 0:
            all_solutions.append(solution)
        else:
            stepsize = vector[position]
            findAllPaths(vector, position + stepsize, solution, all_solutions) #step forward
            findAllPaths(vector, position - stepsize, solution, all_solutions) #step back
    return all_solutions

def findPaths(vector):
    paths = findAllPaths(vector, 0, [], [])
    if paths:
        return paths
    else:
        print("No possible path")
        return 0

编辑:

每次递归调用都会产生一个新的堆栈框架,这是一个包含函数参数和在该调用期间创建的任何局部变量的内存块。每个调用依次进行两次递归调用,每个调用都有自己的堆栈帧位于前一个的顶部。这个不稳定的宽塔堆栈帧称为调用堆栈,并跟踪递归函数的执行。最终,我们要么越界,要么达到向量中的零,此时我们返回我们的解决方案。正如您正确地注意到的,此堆栈帧中 position 的值是 11。当我们点击 return 语句时,返回值被传递到堆栈中的前一帧,而当前堆栈帧中的所有其他内容都被丢弃.通过这种方式,每个堆栈帧以及每个递归调用都会为 position 维护一个不同的值,该值不会影响调用它的函数中的 position 值。

那么我们如何确保我们没有重复的解决方案?在每次递归调用后考虑候选解决方案。对具有长度为 n 的候选解的 findAllPaths 调用要么终止(如果 vector[position] == 0),要么对 findAllPaths 进行两次递归调用,每次调用的解的长度为 n + 1。在这种情况下,两个相应候选解决方案的最后一个元素是position + vector[position]position - vector[position]。这些是相同的 iff vector[position] == 0],在这种情况下我们已经终止了。因此,我们递归调用中的两个候选解是不同的,并且候选解的长度随着每次递归调用而增加。综合起来,这两个事实意味着我们在解决方案中永远不可能有相同的路径。