[英]Python tail recursion optimization in this algo?
我遇到了以下問題:讓我們考慮以下編碼表:
0 -> A
1 -> B
2 -> C
...
"0" -> 1 (word is A)
"10" -> 2 (words are BA and K)
"121" -> 3 (words are BCB, MB and BV)
我寫了這個算法
import string
sys.setrecursionlimit(100) # limit the number of recursions to 100
# {0: 'a', 1: 'b', etc.}
dict_values = dict(zip(range(26), string.ascii_lowercase))
def count_split(list_numbers: list) -> int:
if len(list_numbers) == 0:
return 0
elif len(list_numbers) == 1:
return 1
elif len(list_numbers) == 2:
if int(list_numbers[0]) == 0:
return 1
elif 10 <= int("".join(list_numbers)) <= 25:
return 2
else:
return 1
else: # list_numbers contains at least three elements
if count_split(list_numbers[:2]) == 2:
return count_split(list_numbers[1:]) + count_split(list_numbers[2:])
else:
return count_split(list_numbers[1:])
def get_nb_words(code: str) -> int:
return count_split(list(code))
# print(get_nb_words("0124")) -> 3
# print(get_nb_words("124")) -> 3
# print(get_nb_words("368")) -> 1
# print(get_nb_words("322")) -> 2
# print(get_nb_words("12121212121212121212")) -> 10946
令人驚訝的是,該算法適用於最后一個示例"12121212121212121212"
。 我預計會超過遞歸次數,因為在每個步驟中,函數count_split
在列表中被調用兩次。 這樣一來,調用次數就遠遠超過100次(甚至超過1000次)!
與此同時,我在 stackoverflow 上發現這篇文章說尾遞歸沒有在 Python 中優化,所以我有點驚訝!
有人可以向我解釋為什么在這個算法中沒有超過遞歸限制嗎?
您關心遞歸深度,即調用堆棧的最大深度(高度?)。
這是一種經驗方法:(測量深度的代碼)
import string, sys
sys.setrecursionlimit(100) # limit the number of recursions to 100
dict_values = dict(zip(range(26), string.ascii_lowercase))
stack = []
max_depth = 0
def count_split(list_numbers: list) -> int:
global max_depth
stack.append(None)
max_depth = max(max_depth, len(stack))
if len(list_numbers) == 0:
return 0
elif len(list_numbers) == 1:
return 1
elif len(list_numbers) == 2:
if int(list_numbers[0]) == 0:
return 1
elif 10 <= int("".join(list_numbers)) <= 25:
return 2
else:
return 1
else: # list_numbers contains at least three elements
if count_split(list_numbers[:2]) == 2:
stack.pop()
result = count_split(list_numbers[1:]) + count_split(list_numbers[2:])
stack.pop(); stack.pop()
return result
else:
result = count_split(list_numbers[1:])
stack.pop()
return result
def get_nb_words(code: str) -> int:
return count_split(list(code))
print(get_nb_words("12121212121212121212"))
print(max_depth) # 20
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.