Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 即使基本情况是完美的,递归也不会终止_Python_Algorithm_Python 3.x_Recursion_Dynamic Programming - Fatal编程技术网

Python 即使基本情况是完美的,递归也不会终止

Python 即使基本情况是完美的,递归也不会终止,python,algorithm,python-3.x,recursion,dynamic-programming,Python,Algorithm,Python 3.x,Recursion,Dynamic Programming,我一直在试图解决这个问题。我的想法是尝试所有可能的组合,如果它有效的话,我会继续记忆。但实际上递归并没有停止。这是我的算法 这是我写的代码: def min_edits(s1, s2): if len(s1) == 0 and len(s2) == 0: return 0 elif len(s1) == 0 or len(s2) == 0: return float("inf") elif s1[0] == s2[0]: r

我一直在试图解决这个问题。我的想法是尝试所有可能的组合,如果它有效的话,我会继续记忆。但实际上递归并没有停止。这是我的算法

这是我写的代码:

def min_edits(s1, s2):
    if len(s1) == 0 and len(s2) == 0:
        return 0
    elif len(s1) == 0 or len(s2) == 0:
        return float("inf")
    elif s1[0] == s2[0]:
        return 1 + min_edits(s1[1:], s2[1:])
    else:
        replace = min_edits(s2[0] + s1[1:], s2)  # Replace the first character of first string with that of second one
        insert = min_edits(s2[0] + s1, s2)  # Adds the first character of second string to first one
        delete = min_edits(s2[1:], s2)  # delete first character of first string
        return min(
            insert,
            replace,
            delete
        )


if __name__ == '__main__':
    tc = int(input())
    for i_tc in range(tc):
        input()
        (s1, s2) = input().split(" ")
        answer = min_edits(s1, s2)
        print(answer)
这是递归树:

在递归树中,第一个分支是replace,第二个分支是insert,最后一个分支是delete

“389;”表示只有一个字符串为空,函数返回无穷大

因此,我们可以清楚地看到,树在任何情况下都会被终止

但它仍然表示超过了最大递归深度

请告诉我哪里做错了。谢谢:)


问题在于参数的长度并不是每一步都在减少,这对于递归调用到达基本情况至关重要。在replace中,两个字符串的长度保持不变,而在insert步骤中,一个字符串的长度实际上会增加

那么,替换、移除或插入是什么意思?例如,假设我们有字符串:

ABCD and DECD
然后,如果我们查看索引0,那么replace/remove调用将留给我们BCD&ECD,insert将留给我们ABCD&ECD或BCD&DECD。使用这种方法,至少一个字符串的长度总是减少,因此我们可以保证达到基本情况

编辑:基本情况已达到,但逻辑存在问题,因此我添加了解决问题的方法:

def min_edits(s1, s2):
if len(s1) == 0:
    return len(s2)
if len(s2) == 0:
    return len(s1)
elif s1[0] == s2[0]:
    return min_edits(s1[1:], s2[1:]) #characters match, no additional cost here
else:
    replace = min_edits(s1[1:], s2) + 1  # Insert into second string
    insert = min_edits(s1, s2[1:]) + 1  # Insert into first string
    delete = min_edits(s1[1:], s2[1:]) + 1  # replace/remove from both strings
    return min(
        insert,
        replace,
        delete
    )

我想,递归的非终止性对您来说是一个输入错误

在最后一部分中,“delete=min_edits(s2[1:],s2)”代码应为“delete=min_edits(s1[1:],s2)”。因为我们正在删除第一个字符串的第一个字符,并保留其余字符

以下代码为我正确终止

else:
    replace = min_edits(s2[0] + s1[1:], s2)  # Replace the first character of first string with that of second one
    insert = min_edits(s2[0] + s1, s2)  # Adds the first character of second string to first one
    delete = min_edits(s1[1:], s2)  # delete first character of first string
    return min(
        insert,
        replace,
        delete
    )
但编辑成本的计算是不恰当的。您可能希望将其移动到实际执行编辑操作的位置。像下面这样的东西

else:
    replace = min_edits(s1[1:], s2[1:]) + 1  # If a replace operation is performed, then s1[0] == s2[0].  As, they have matched reduce the problem to match new strings s1[1:], s2[1:]
    insert = min_edits(s1, s2[1:]) + 1  # If an insert operation is performed @ s1, then s1[0] == s2[0]. As, they have matched reduce the problem to match new strings s1,s2[1:]
    delete = min_edits(s1[1:], s2) + 1  # If an insert operation is performed @ s1. Reduce the problem to match new strings s1[1:], s2

    return min(
        insert,
        replace,
        delete
    )

希望有帮助

1)对于
len(s1)==0或len(s2)==0
,为什么返回无穷大而不是任何非空单词的长度?2) 对于
s1[0]==s2[0]
,如果第一个字符相同,为什么要在返回值中添加1?例如,如果进入函数的两个字符串是“b”和“b”,则根据算法,下一级将是两个空字符串。所以在上一步中,它们被转换了,所以我返回1如果其中只有一个是空字符串,那么这意味着它不能继续。即使它走得更远,也会导致无限的永无止境的循环。所以我返回无穷远,看起来它确实终止了,但它可能需要很长时间。如果出现“堆栈超出”错误,可能是因为传递了一个长字符串。Python堆栈限制有点小,递归实现并不适合这个问题。1)每个调用都不应该执行递归层次结构中上一个调用的工作,因此当它们相同时,不应该添加1。2) 如果其中只有一个是空字符串,为什么不能继续?只需添加或删除非空字符串中的字母数,或者如果两者都为空,则返回零。在递归树中,您可以看到一个字符串后面的路径肯定会变为空,并返回无穷大。在replace情况下,两个字符串都将从下一个索引中切片。因此,它将到达基本大小写。它将在delete递归调用的下一个索引中被切片,而不是在insert或replace调用中被切片。考虑在只替换递归调用的路径中发生的情况。它永远不会到达基本情况。不,它正在到达基本情况。这只是一个打字错误。:)我非常喜欢你在方法调用中添加+1的方法。事实上,在这之前我得到了错误的答案,现在我得到了正确的答案。你已经删除了你的方法。很好。请保留它。你给方法调用添加+1的方法给了我一个新的直觉,所以我将此标记为答案。谢谢,它正在减少…我玩得很好。我没有得到递归深度(stackoverflow错误)任何时候@bharath代码“replace=min_edits(s2[0]+s1[1:],s2)”和“insert=min_edits(s2[0]+s1,s2)”绝对不会减少当前递归调用的问题大小。这是DP“最优子结构”的一个重要性质。它达到基本情况man。仔细看。传递两个字符串后,将在函数开头对其求值。如果它们在一开始是相同的,它们将是相同的sliced@bharath你是对的。我忽略了它。我找到了递归不终止的根本原因。我已经更新了答案。