[英]How to apply a backtracking algorithm?
我正在Python課程中做一些練習,其中一個我遇到的問題如下:
Given a digit sequence that represents a message where each uppercase letter
is replaced with a number (A - 1, B - 2, ... , Z - 26) and space - 0.
Find the number of the initial messages, from which that sequence
could be obtained.
Example: 12345 - 3 (ABCDE, LCDE, AWDE)
11 - 2 (AA, K)
天真的解決方案很簡單,它是簡單的強力算法:
import string
def count_init_messages(sequence):
def get_alpha(seq):
nonlocal count
if len(seq) == 0:
count += 1
return
for i in range(1, len(seq) + 1):
if seq[:i] not in alph_table:
break
else:
get_alpha(seq[i:])
alphabet = " " + string.ascii_uppercase
# generate dictionary of possible digit combination
alph_table = {str(n): alph for n, alph in zip(range(len(alphabet)), alphabet)}
# counter for the right combination met
count = 0
get_alpha(sequence)
return count
def main():
sequence = input().rstrip()
print(count_init_messages2(sequence))
if __name__ == "__main__":
main()
但由於輸入序列的長度可能長達100個字符,並且可能存在大量重復,因此我遇到了時間限制。 例如,樣本輸入之一是2222222222222222222222222222222222222222222222222222222222222222222222 (possible messages number is 308061521170129)
。 由於我的實現過多重復,處理這樣的輸入需要很長時間。 我想使用回溯算法,但我還沒有意識到如何實現成功結果的memoization。
如果能夠以正確的方式指出我如何打破這項任務,我會很高興的。
你必須解決的遞歸關系(其中s
是一串數字, a
和b
是單個數字)是這樣的:
S("") = 1
S(a) = 1
S(s + a + b) = S(s+a) + (S(s) if ab is between 10 and 26)
這可以使用動態編程而不是回溯來計算。 如果你做得對,它的O(n)時間復雜度和O(1)空間復雜度。
def seq(s):
a1, a2 = 1, 1
for i in xrange(1, len(s)):
a1, a2 = a1 + (a2 if 9 < int(s[i-1:i+1]) < 27 else 0), a1
return a1
print seq('2222222222222222222222222222222222222222222222222222222222222222222222')
查找表中的最大數字是26,因此您永遠不需要查找長度大於2的字符串。相應地修改for循環。 這可能足以使蠻力可行。
您可能還認可308061521170129為第71個斐波那契數字。 這種關系與Fibonacci數字相對應,給出了“某些枚舉問題的解決方案。最常見的問題是計算總和為n的1和2的組合數:有Fn + 1種方法可以做到這一點“( https://en.wikipedia.org/wiki/Fibonacci_number#Use_in_mathematics )。
字符串中可以分成單個或雙個數字代碼的每個連續子序列表示具有1和2的多個可能組合的n
; 因此,對於字符串中的每個這樣的子序列,結果必須乘以(子序列的長度+ 1)斐波納契數(在70 2的情況下,我們只乘以第71個斐波納契數)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.