[leetcode][牛客]關於使用Python答題時報maximum recursion depth exceeded in comparison的劣勢和解決方法

在Leetcode等刷題網站刷題時,爲了方便少敲分號,我經常會選擇用python;但頭疼的是,同樣的算法有時候C++能過但python不能過,比如關於Python答題時報maximum recursion depth exceeded in comparison,往往是因爲用了遞歸算法,當深度過深時被python虛擬機直接拒絕了。


舉例

牛客題目地址:https://www.nowcoder.com/practice/52f25c8a8d414f8f8fe46d4e62ef732c

題目描述
小多想在美化一下自己的莊園。他的莊園毗鄰一條小河,他希望在河邊種一排樹,共 MM 棵。小多采購了 NN 個品種的樹,每個品種的數量是 AiA_i (樹的總數量恰好爲 MM)。但是他希望任意兩棵相鄰的樹不是同一品種的。小多請你幫忙設計一種滿足要求的種樹方案。
輸入描述:
第一行包含一個正整數 NN,表示樹的品種數量。
第二行包含 NN 個正整數,第 ii (1iN1 \le i \le N) 個數表示第 ii 個品種的樹的數量。
數據範圍:

1N10001 \le N \le 1000
1M20001 \le M \le 2000

輸出描述:
輸出一行,包含 M 個正整數,分別表示第 i 棵樹的品種編號 (品種編號從1到 N)。若存在多種可行方案,則輸出字典序最小的方案。若不存在滿足條件的方案,則輸出"-"。
示例:

輸入

3
4 2 1

輸出

1 2 1 2 1 3 1


解題思路

這道題本身就是一個DFS加上剪枝,但是受限於python默認的最大遞歸深度,會出現某些數據爆函數棧的問題,而同樣的算法使用C++則不會有問題。例如:

N = int(input())
arr = list(map(int, input().split())) # sum(arr) = M
M, res = sum(arr), []


def dfs(a, m, prev_tree_class):
    global res
    if m == 0:
        return True
    for i in range(len(a)):
        if a[i]*2 > m+1: # 減枝條件
            return False # 當某一類樹剩餘數量大於坑位的一半時不可能滿足題意
            
        tree_class = i+1
        if a[i] > 0 and prev_tree_class != tree_class:
            a[i] -= 1 # 種一棵
            res.append(tree_class)
            if dfs(a, m-1, tree_class):
                return True
            res.pop(-1) # 不滿足則回退
            a[i] += 1
    return False
    
# 字典序取小,則從第0類樹開始探測
print(" ".join(map(str, res)) if dfs(arr, M, 0) else "-")

解決方案

# 在開頭加上
import sys # python 默認遞歸深度不超過1000,做dfs會比C吃虧
sys.setrecursionlimit(10000000)# 手動修改深度
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章