微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

以记忆化的功能递归方式实现迭代解决方案

如何解决以记忆化的功能递归方式实现迭代解决方案

我正在尝试解决 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'

例如,如果调用 (2,1) of sum = 2 和 coin-array-index = 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,'ENTER')]
    calls = 0
    while len(stack)!=0:
        currentsum,instruction = stack.pop()
        if currentsum == amount:
            d[(currentsum,index)] = 1
            continue
        elif instruction == 'ENTER':
            stack.append((currentsum,'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,'ENTER'))
        elif instruction == 'EXIT':
            newsum = currentsum + coins[index]
            left = 0 if d.get((newsum,None) == None else d.get((newsum,index))
            right = 0 if d.get((currentsum,None) == None else d.get((currentsum,index+1))
            d[(currentsum,index)] = left+right
        calls = calls+1
    print(calls)
    return d[(0,0)]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。