我一直在关注这一点,我试图获得一些将普通递归函数转换为尾部递归函数的实践。我设法理解斐波那契和阶乘的版本,但这一个难住了我。我理解算法在做什么,以及在转换中让我困惑的else语句。
在else中,它试图找到一个更接近你想要的数字,然后放弃,并继续使用它找到的数字,该数字低于你建议的数字。
我不知道如何编写使这个尾部递归的辅助函数。对于斐波那契和阶乘,我最终使用了累加器。有没有类似的东西可以在这里使用?
class BSTNode(object):
"""Binary search tree node."""
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
def __repr__(self):
return '(%s, %r, %r)' % (self.val, self.left, self.right)
def find_val_or_next_smallest(bst, x):
"""
Get the greatest value <= x in a binary search tree.
Returns None if no such value can be found.
"""
if bst is None:
return None
elif bst.val == x:
return x
elif bst.val > x:
return find_val_or_next_smallest(bst.left, x)
else:
right_best = find_val_or_next_smallest(bst.right, x)
if right_best is None:
return bst.val
return right_best
我知道Python不支持尾部递归优化以允许恒定的堆栈空间,但我只是为了在Python中练习,因为我喜欢语法
要将函数转换为尾部递归函数,您应该通过添加一个额外的参数val始终携带部分答案:
def find_val_or_next_smallest(bst, x, val=None):
"""
Get the greatest value <= x in a binary search tree.
Returns None if no such value can be found.
"""
if bst is None:
return val
elif bst.val == x:
val = x
elif bst.val < x and (val is None or bst.val > val):
val = bst.val
if bst.val > x:
return find_val_or_next_smallest(bst.left, x, val)
else:
return find_val_or_next_smallest(bst.right, x, val)
更新
拥有尾递归意味着我们可以有一个迭代解决方案(与递归相比),并且可以很容易地在接受的答案上进行演示——通过将其转换为迭代解决方案:
def find_val_or_next_smallest(bst, x, val=None):
"""
Get the greatest value <= x in a binary search tree.
Returns None if no such value can be found.
"""
while True:
if bst is None:
return val
elif bst.val == x:
return x
elif bst.val > x:
bst = bst.left
else:
val = bst.val
bst = bst.right
而不是做
if right_best is None:
return bst.val
您可以将目前为止找到的最佳结果作为额外参数传递给递归调用,并让递归调用处理此检查。
def find_val_or_next_smallest(bst, x, best=None):
"""
Get the greatest value <= x in a binary search tree.
Returns None if no such value can be found.
"""
if bst is None:
return best
elif bst.val == x:
return x
elif bst.val > x:
return find_val_or_next_smallest(bst.left, x, best)
else:
# bst.val is guaranteed to be the best yet, since if we had
# seen a better value higher up, the recursion would have gone
# the other way from that node
return find_val_or_next_smallest(bst.right, x, bst.val)
我有一个家庭作业问题,它给出了一个递归函数,我必须使用尾部递归来实现它。函数为f(0)=1 f(n)=1 2*f(n-1) 我并不擅长尾部递归,我试着查找示例,但我发现的都是没有斐波那契序列的示例,这没有多大帮助。 我真正拥有的是 我知道尾递归基本上每次调用都计算函数,我只是不知道如何实现它。 编辑:我打了一个错字f(n)应该是1 2*f(n-1)
各种各样的书籍、文章、博客帖子表明,将递归函数重写为尾部递归函数可以加快速度。毫无疑问,对于生成斐波那契数或计算阶乘等琐碎情况,它会更快。在这种情况下,有一种典型的重写方法,即使用“辅助函数”和用于中间结果的附加参数。 尾部递归很好地描述了尾部递归函数和非尾部递归函数之间的差异,以及如何将递归函数转换为尾部递归函数。对于这种重写来说什么是重要的-函数调用的数量是相同的(重写之前/之后),不同之处在
我仍在尝试实现2-3个手指树,并取得了良好的进展(存储库)。在做一些基准测试时,我发现当树非常大时,我非常基本的toList会导致堆栈溢出异常。起初,我看到了一个简单的修复方法,并将其设置为尾部递归。 不幸的是,事实证明,toList不是罪魁祸首,但viewr是: 寻找唯一的递归调用很明显,这不是尾部递归。不知何故,我希望这个问题不会存在,因为这个调用被包装在一个类似于连续的延迟中。 我听说并读过
假设我编写这样的代码: 我如何让Kotlin优化这些相互递归的函数,以便在不抛出StackOverflower错误的情况下运行main?tailrec关键字适用于单函数递归,但没有更复杂的功能。我还看到一个警告,在使用关键字tailrec的地方没有找到尾部调用。也许这对编译器来说太难了?
在我的Scala应用程序中,我有一个函数调用一个函数,该函数返回Future[T]类型的结果。我需要在递归函数调用中传递映射的结果。我希望这是尾递归的,但地图(或flatMap)正在破坏这样做的能力。我收到错误“递归调用不在尾部位置”。 下面是这个场景的一个简单示例。如何修改它以使调用是尾部递归的(而不破坏使用Await.result()的未来的好处)?
嗯,我已经试过多次了。不过,我一度认为最长的序列函数会有所帮助,因为它显示的是最长的冰雹序列。尽管如此,我似乎不知道如何查找或存储它用于查找的值。如果有人能解释一下,我将不胜感激。 我遇到的问题是我最长的启动顺序: 我不知道如何将其转换为递归,我注意到对于一些递归,我看到人们仍然在使用for循环,但我确信我们不应该使用循环。这可能是一个愚蠢的问题,但如果有人知道的话,有没有一个公式可以将循环转换为