【问题标题】:Implementing iterative solution in a functionally recursive way with memoization使用记忆化以功能递归的方式实现迭代解决方案
【发布时间】:2021-06-22 03:26:37
【问题描述】:

我正在尝试解决 leetcode 上的以下问题:Coin Change 2

输入:金额 = 5,硬币 = [1, 2,5] 输出:4 解释:有四种方式补足:

5=5

5=2+2+1

5=2+1+1+1

5=1+1+1+1+1

我正在尝试实现一个迭代解决方案,该解决方案本质上是使用堆栈模拟/模仿递归。我已经设法实现它并且解决方案有效,但它超过了时间限制。

我注意到递归解决方案利用记忆进行优化。我也想将其合并到我的迭代解决方案中,但我不知道如何继续。

到目前为止我的解决方案:

# stack to simulate recursion
stack = []
# add starting indexes and sum to stack
#Tuple(x,y) where x is sum, y is index of the coins array input
for i in range(0, len(coins)):
    if coins[i]<=amount:
        stack.append((coins[i], i))

result = 0
while len(stack)!=0:
    c = stack.pop()
    currentsum = c[0]
    currentindex = c[1]
    # can't explore further
    if currentsum >amount:
        continue
    # condition met, increment result
    if currentsum == amount:
        result = result+1
        continue
    # add coin at current index to sum if doesn't exceed amount (append call to stack)
    if (currentsum+coins[currentindex])<=amount:
        stack.append((currentsum+coins[currentindex], currentindex))
    #skip coin at current index (append call to stack)
    if (currentindex+1)<=len(coins)-1:
        stack.append((currentsum, currentindex+1))

return result

我曾尝试使用字典来记录附加到堆栈,如下所示:

#if the call has not already happened, add to dictionary
if dictionary.get((currentsum, currentindex+1), None) == None:
   stack.append((currentsum, currentindex+1))
   dictionary[currentsum, currentindex+1)] = 'visited'

例如,如果调用 sum = 2 且 coin-array-index = 1 的 (2,1),我将其附加到字典中。如果再次遇到相同的呼叫,我不会再次附加它。但是,它不起作用,因为不同的组合可以具有相同的总和和索引。

无论如何我可以在上面的迭代解决方案中加入记忆。我想以一种在功能上与递归解决方案相同的方式来做。

【问题讨论】:

  • 您对有效的动态规划方法感兴趣吗?
  • 我了解自下而上的动态编程方法,但我正在尝试通过记忆实现自上而下的迭代,本质上是使用堆栈迭代地模拟递归解决方案
  • 好的,我明白了.......看看我的答案。我会说这是自上而下的方法。
  • 我想知道是否可以在我采用的迭代方法中模拟记忆?我本质上是使用堆栈迭代地模拟递归解决方案,但是,我想向其中添加记忆优化。

标签: algorithm recursion data-structures stack iteration


【解决方案1】:

我已经设法找出解决方案。本质上,我使用了后序遍历并使用状态变量来记录当前调用所处的递归阶段。使用该阶段,我已经设法在自上而下后自下而上。

我想出的解决方案如下:

def change(self, amount: int, coins: List[int]) -> int:
    if amount<=0:
        return 1
    if len(coins) == 0:
        return 0  
    d= dict()
    #currentsum, index, instruction
    coins.sort(reverse=True)
    stack = [(0, 0, 'ENTER')]
    calls = 0
    while len(stack)!=0:
        currentsum, index, instruction = stack.pop()
        if currentsum == amount:
            d[(currentsum, index)] = 1
            continue
        elif instruction == 'ENTER':
            stack.append((currentsum, index, 'EXIT'))
            
            if (index+1)<=(len(coins)-1):
                if d.get((currentsum, index+1), None) == None:
                    stack.append((currentsum, index+1, 'ENTER'))
            
            newsum = currentsum + coins[index]
            if newsum<=amount:
                if d.get((newsum, index), None) == None:
                    stack.append((newsum, index, 'ENTER'))
        elif instruction == 'EXIT':
            newsum = currentsum + coins[index]
            left = 0 if d.get((newsum, index), None) == None else d.get((newsum, index))
            right = 0 if d.get((currentsum, index+1), None) == None else d.get((currentsum, index+1))
            d[(currentsum, index)] = left+right
        calls = calls+1
    print(calls)
    return d[(0,0)]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-22
    • 2020-08-09
    • 1970-01-01
    • 2018-10-07
    • 2021-02-17
    • 2020-06-07
    • 2020-10-30
    • 2021-06-23
    相关资源
    最近更新 更多