【问题标题】:Recursive function return value without allocating extra space?递归函数返回值而不分配额外空间?
【发布时间】:2020-12-26 03:11:02
【问题描述】:

所以我一直在尝试优化这个名为 Frog Jump 的 LeetCode 问题。以下是问题的基本描述:

给定一个按升序排列的石头位置列表(以单位为单位),确定青蛙是否能够通过降落在最后一块石头上过河。最初,青蛙在第一块石头上,并假设第一次跳跃必须是 1 个单位。

如果青蛙的最后一次跳跃是 k 个单位,那么它的下一次跳跃必须是 k - 1、k 或 k + 1 个单位。注意青蛙只能向前跳。

例如:[0,1,3,5,6,8,12,17]

总共有 8 块石头。第 0 单元的第一块石头,第二块 第一个单位的石头,第三个单位的第三个石头,依此类推...... 第 17 单元的最后一块石头。

返回真。青蛙可以跳1个单位跳到最后一块石头 到第 2 块石头,然后 2 个单位到第 3 块石头,然后 2 个单位到 第 4 块石头,然后 3 个单位到第 6 块石头,4 个单位到第 7 块石头, 和 5 个单位到第 8 个石头。

这是我的有效解决方案。我需要帮助的是如何在不分配额外的 res 数组的情况下输出相同的布尔值,该数组使用 DFS 存储所有探索路径的逻辑 OR。

class Solution:
    def canCross(self, stones: List[int]) -> bool:
        
        if stones[1] != 1:
            return False
        
        res = []
        memo = {}
        
        def dfs(curr_stone, last_stone, last_jump):
            
            if curr_stone == last_stone:
                res.append(True)
                return
            
            if curr_stone > last_stone:
                res.append(False)
                return
            
            for i in range(-1,2):
                next_stone = curr_stone + (last_jump + i)
                if next_stone in stones and next_stone > curr_stone and (next_stone, last_stone, last_jump+i) not in memo:
                    memo[(next_stone, last_stone, last_jump+i)] = 1
                    dfs(next_stone, last_stone, last_jump+i)
        
        dfs(1, stones[-1], 1)
        return any(res)

有人可以帮助我解决这些问题吗?我总是在这些问题上苦苦挣扎,最终将值存储在数组中;但是,理想情况下,我希望递归代码的结果是相同的,而不分配额外的 res 数组空间。

【问题讨论】:

  • “不分配额外空间”是硬性要求吗?我的第一个想法是动态编程,但这与没有额外空间完全相反。
  • @tobias_k,不是真的,我会说 dp 有效,我只是通过使用记忆字典来做类似的事情。
  • @Carcigenicate,有什么更清晰的方法可以实现吗?我是否将 dfs(next_stone, last_stone, last_jump+i) 的值存储在一个变量中,如果为真则返回 True?否则继续?

标签: python recursion depth-first-search


【解决方案1】:

由于函数的整个目的似乎归结为返回any(res),看来您应该从递归函数返回True/False,而不是附加它们,然后退出所有递归调用一次找到单个 True 值,并且不费心保存每个找到的值。

这将涉及检查从递归调用 dfs(next_stone, last_stone, last_jump+i) 返回的内容,如果是真的,只需返回 True

from typing import List

class Solution:
    def canCross(self, stones: List[int]) -> bool:

        if stones[1] != 1:
            return False

        memo = {}

        def dfs(curr_stone, last_stone, last_jump):

            if curr_stone == last_stone:
                return True  # Return the results instead of appending them to a list

            if curr_stone > last_stone:
                return False

            for i in range(-1, 2):
                next_stone = curr_stone + (last_jump + i)
                if next_stone in stones and next_stone > curr_stone and (next_stone, last_stone, last_jump + i) not in memo:
                    memo[(next_stone, last_stone, last_jump + i)] = 1
                    rec_result = dfs(next_stone, last_stone, last_jump + i)
                    if rec_result:  # Then check the recursive results at the call-site
                        return True

        return dfs(1, stones[-1], 1)

我会注意,我没有对此进行广泛的测试,但从一些快速的“头部解释”来看,它似乎是等效的。

【讨论】:

    猜你喜欢
    • 2020-10-10
    • 2022-07-21
    • 2020-10-17
    • 1970-01-01
    • 2018-01-03
    • 2017-09-24
    • 2021-03-02
    • 1970-01-01
    相关资源
    最近更新 更多