如何限制python中的递归深度?

时间:2017-02-16 19:58:57

标签: python recursion

我有一个元素列表。我想知道列表中是否有两对元素,其中元素的元素具有相同的值。

我的想法是,我首先比较列表中的所有元素,如果找到一对,则从列表中删除该对,然后再次继续。因此,我认为我可以使用递归来完成此任务,但将深度限制为2以解决问题。

这是我的第一次尝试:

    recursion_depth=0
        def is_twopair(card):
            nonlocal recursion_depth
            if recursion_depth==2: return True
            for i in range(0, len(card)):
                for k in range(i+1,len(card)):
                    if card[i].value==card[k].value:
                        del card[k], card[i]
                        recursion_depth+=1
                        is_twopair(card)      
                    else: continue
                else: continue
            else: return False

我使用变量recursion_depth来记录递归的深度,但后来意识到return命令不会立即终止该函数并返回true,而是返回其原始调用者is_twopair(card)。所以我的问题是:

  1. 有没有办法立即终止函数并返回结果为真?
  2. 有没有办法限制递归的深度?
  3. 我知道可能有几种方法可以解决这个问题。但我希望对我的想法保持忠诚,并将其作为学习的机会。

3 个答案:

答案 0 :(得分:1)

我不相信你可以"爆发"没有一些严重的黑魔法的递归,我也不相信你应该尝试。将返回值级联到调用链通常是一种很好的方法。

我个人避免使用非局部变量并跟踪每个函数调用范围内的递归深度。

def remove_pairs(card, count=2, depth=0):
    if depth == count:
        return card

    for i in range(0, len(card)):
        for j in range(i+1, len(card)):
            if card[i].value == card[j].value:
                del card[j], card[i]
                return remove_pairs(card, count, depth+1) # add return here

将深度跟踪移动到函数本身将允许从不同位置重复调用该函数而不会出现问题。

此外,可以使用itertools.combinations清除代码。

from itertools import combinations

def remove_pairs(cards, count=2, depth=0):
    if depth == count:
        return cards

    for card1, card2 in combinations(cards, 2):
        if card1.value == card2.value:
            cards.remove(card1)
            cards.remove(card2)
            return remove_pairs(cards, count, depth+1)

答案 1 :(得分:0)

yourList = [1,1,2,2,3,4]
yourDict = {}
for i in yourList:
    yourDict[i] = yourList.count(i)

此代码将返回列表中每个值的出现次数,以便您确定对的数量。

在这种情况下:

  

yourDict - - > {1:2,2:2,3:1,4:1}

值1出现2次,值2出现2次,值3和4出现1次。

答案 2 :(得分:0)

我认为您丢失的内容是return调用,将递归回调的结果传递给前一个调用者:

if card[i].value==card[k].value:
    del card[k], card[i]
    recursion_depth+=1
    return is_twopair(card)       # add return here!

我真的不认为递归是解决这个问题的自然方法,但是通过上述改变,它应该可行。您可以通过将nonlocal作为可选参数传递来避免使用depth变量。