当前位置: 首页 > 知识库问答 >
问题:

用函数递归的方法实现迭代求解

段干河
2023-03-14

我正在尝试解决leetcode上的以下问题:硬币兑换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数组index=1的调用(2,1),我将其附加到字典中。如果再次遇到相同的调用,我不会再次追加它。但是,它不起作用,因为不同的组合可以有相同的总和和索引

不管怎样,我可以在上面的迭代解决方案中加入记忆化。我想这样做,使它在功能上与递归解决方案相同。

共有1个答案

虞安康
2023-03-14

我设法找到了解决办法。本质上,我使用了后序遍历,并使用状态变量来记录当前调用所处的递归阶段。在舞台上,我在自上而下之后,成功地做到了自下而上。

我提出的解决方案如下:

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)]
 类似资料:
  • 本文向大家介绍C++实现递归函数的方法,包括了C++实现递归函数的方法的使用技巧和注意事项,需要的朋友参考一下 递归函数通俗来讲就是自己调用自己本身。这样有很大的好处,代码很方便简洁,把复杂的有规律的运算交给计算机去做。 1、首先定义问题。递归函数(recursion)需要设置一个函数,然后再可以循环往复的执行下去。 2、把问题换成公式。 如把阶乘之和定义为f(n)=n*f(n-1)。也就是说n*

  • 我在scheme中构建了一个递归函数,它将在一些输入上重复给定的函数f,n次。 我需要用尾递归构建这个函数的迭代版本,如果我正确理解尾递归,我认为我做得对。 我的问题是,这真的是迭代的吗?我相信我已经使用尾部递归正确地构建了它,但从技术上讲,它仍然将一系列操作推迟到count=0,在这里,它执行叠加的任意多个组合。

  • 本文向大家介绍php使用递归函数实现数字累加的方法,包括了php使用递归函数实现数字累加的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了php使用递归函数实现数字累加的方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的php程序设计有所帮助。

  • 本文向大家介绍Python实现链表反转的方法分析【迭代法与递归法】,包括了Python实现链表反转的方法分析【迭代法与递归法】的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Python实现链表反转的方法。分享给大家供大家参考,具体如下: Python实现链表反转 链表反转(while迭代实现): 链表的反转引入一个cur_node变量,表示当前节点;同时需要引入一个变量new_link表

  • 如果说在任何地方都使用递归,那么可以使用for循环,对吗?如果递归通常比较慢,那么将其用于循环迭代的技术原因是什么? 如果总是可以将递归转换为for循环,那么有经验法则吗?