我正在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)
。由于我的实现过多重复,处理这样的输入需要很长时间。我想使用回溯算法,但我还没有意识到如何实现成功结果的记忆。
如果能够以正确的方式指出我如何打破这项任务,我会很高兴。
答案 0 :(得分:4)
您必须解决的递归关系(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')
答案 1 :(得分:0)
查找表中的最大数字是26,因此您永远不需要查找长度大于2的字符串。相应地修改for循环。这可能足以让蛮力生存。
答案 2 :(得分:0)
您可能还认可308061521170129为第71个斐波那契数字。这种关系与Fibonacci数字相对应,给出了某些枚举问题的解决方案。最常见的问题是计算总和为给定总数n的1和2的组合数:有Fn + 1种方法可以做到这一点&#34; (https://en.wikipedia.org/wiki/Fibonacci_number#Use_in_mathematics)。
字符串中可以分为单个或两个数字代码的每个连续子序列表示具有1和2的多个可能组合的n
;因此,对于字符串中的每个这样的子序列,结果必须乘以(子序列长度+ 1)斐波那契数(在70 2&#39; s的情况下,我们只乘以1乘以71斐波那契数字。)