在递归函数中用尾递归替换for循环

时间:2018-09-12 18:13:09

标签: python algorithm recursion computer-science tail-recursion

我正在尝试使以下函数完全尾部递归,例如让烦人的循环从那里出来。原因是我正在尝试将解决方案轻松转换为涉及使用显式堆栈的迭代解决方案。请告知。

def permutations(A):
    P = []
    P2 = []
    permutations_recursive(A, [], P)
    permutations_tail_recursive(A, [], P2, 0)
    print(P2)
    return P

def permutations_recursive(first, last, perms):
    if len(first) == 0:
        perms.append(last)
    else:
        for i in range(len(first)):
            permutations_recursive(
                first[:i] + first[i+1:],
                last + [first[i]],
                perms)

2 个答案:

答案 0 :(得分:0)

关闭迭代类似物:

!var!

答案 1 :(得分:0)

一个完全递归的函数应该是:

def permutations_comp_recursive(first, last, perms, i):
    if len(first) == 0:
        perms.append(last)
    elif i == len(first):
        pass
    else:
        permutations_comp_recursive(first, last, perms, i+1)
        if first:
                permutations_comp_recursive(
                first[:i]+first[i+1:],
                last + [first[i]],
                perms, 0)

为了获得良好的性能,我建议使用numpy solutions

编辑1:现在,以下内容应使用列表推导进行尾部递归。这使用workarount进行python的尾递归(并且省略了最后2个参数-结果作为返回值传递):

import itertools as it
class Recurse(Exception):
    def __init__(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs

def recurse(*args, **kwargs):
    raise Recurse(*args, **kwargs)

def tail_recursive(f):
    def decorated(*args, **kwargs):
        while True:
            try:
                return f(*args, **kwargs)
            except Recurse as r:
                args = r.args
                kwargs = r.kwargs
                continue
    return decorated

@tail_recursive
def permutations_tail_recursive(first, last, direct=False):
    if len(first) == 0 or not all(first):
        return last
    else:
        l = len(first[0]) if direct else len(first)
        if last:
            return recurse([fi[:i]+fi[i+1:] for fi, i in it.product(first, range(l))],
                [last[j] + first[j][i] for j, i in it.product(range(len(last)), range(l))], True)
        else:
            return recurse([first[:i]+first[i+1:] for i in range(l)],
                [first[i] for i in range(l)], True)

这不是经过优化的,而是使用循环。我不确定是否可以将其与上面没有循环的代码进行组合-可能会再次调查。 itertools.permutations可用于此应用程序。