我正在做一些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)。由于我的实现重复次数太多,处理这样的输入需要很长时间。我想使用回溯算法,但我还没有意识到如何实现回忆录的后续结果。
如果有可能告诉我如何完成这项任务,我会很高兴的。
发布于 2016-10-01 22:38:00
您必须解决的递归关系(其中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')发布于 2016-10-01 22:24:13
查找表中最大的数字是26,所以您永远不需要查找长度大于2的字符串。相应地修改for循环。这可能足以使野蛮人的力量变得可行。
发布于 2016-10-02 04:05:42
您可能还识别了308061521170129作为第71斐波那契数。这种关系对应于Fibonacci数,它给出了“某些枚举问题的解”。最常见的问题是,计算1s和2s的组合数,它们之和为给定的n:有Fn+1方法可以做到这一点。
字符串中的每个连续子序列都可以划分为单数码或双位码,表示具有多个可能组合为1s和2s的n;因此,对于字符串中的每个这样的子序列,结果必须乘以(子序列的长度+ 1)斐波那契数(在702 s的情况下,我们只是将1乘以71斐波那契数)。
https://stackoverflow.com/questions/39811963
复制相似问题