如果a = 1,则b = 2,c = 3,...... z = 26。我想找到字符串可以使用Python生成的可能代码的数量
例如:
get_combination('12')
Output: 2
// The possible decodings are "AB", "L"
get_combination('121')
Output: 3
// The possible decodings are "ABA", "AU", "LA"
get_combination('1234')
Output: 3
// The possible decodings are "ABCD", "LCD", "AWD"
这是代码。但时间的复杂性更多。有人可以比这个更简单的解决方案
def get_combination(string):
def get_branchs(string):
if not string or len(string) == 1:
return 0
if string[0:2] <= '26':
if '0' not in string[1:3]:
return 1 + get_branchs(string[1:]) + get_branchs(string[2:])
else:
return get_branchs(string[2:])
else:
return get_branchs(string[1:])
return 1 + get_branchs(string)
答案 0 :(得分:1)
这是我得到的最简单的形式:
def get_num_codes(number):
if not number:
return 1
# If you want to allow for "stray zeros" at the end remove this if block
if number == "0":
return 0
count = get_num_codes(number[1:])
if number[0] != "0" and len(number) > 1 and number[:2] <= "26":
count += get_num_codes(number[2:])
return count
两个版本的性能相当:
%timeit get_combination("123412432414324231123412")
>>> 1000 loops, best of 3: 1.83 ms per loop
%timeit get_num_codes("123412432414324231123412")
>>> 1000 loops, best of 3: 1.87 ms per loop
答案 1 :(得分:1)
您可以进行以下观察:
让定义一个&#34;相关的子序列&#34; be:如果被视为单独的输入,将返回2个或更多(组合计数)的任何子序列,如果使一个字符更短(从其任一端删除一个字符),则返回较小的值,并且< em> not 如果在子序列的任一侧长1个字符(即不是任何字符,而是作为来自输入的子序列),则返回更大的值。匹配这些相关子序列的正则表达式是
[12]*?(?:[3-6]|1[3-9]|(?=.0|$))
由一个相关子序列表示的组合数由以下递归形式给出(其中n
是子序列的长度):
C(n) = 1 when n == 1
= 2 when n == 2
= C(n-1) + c(n-2) when n > 2
这是Fibonacci系列(由于一个指数位置移位,因为真正的Fibonacci有Fib(2) = 1
,但这只是一个细节。
以下是实施这些想法的评论代码:
import re
from operator import mul
from functools import reduce # For Python 3.x
def get_combination(string):
def fib_to(n):
fibs = [1, 1] # Real Fibonacci would need [0, 1], but we want fib[2] to be 2.
for i in range(2, n+1):
fibs.append(fibs[-1] + fibs[-2])
return fibs
# Detect an invalid sequence, where a 0 occurs without a 1 or 2 preceding it
if re.search(r"(?<![12])0", string):
return 0
# Find all sub sequences where a variation is possible
sequences = re.findall(r"[12]*?(?:[3-6]|1[3-9]|(?=.0|$))", string)
if not sequences:
return 1
# Get the sizes of all these sequences; it is all we need to know
sizes = [len(seq) for seq in sequences]
# Generate Fibonacci numbers up to the maximum needed:
fib = fib_to(max(sizes))
# Take the product of the sizes for each of the sequences
return reduce(mul, [fib[size] for size in sizes], 1)
tests = [ # inputs combined with expected outputs
["", 1],
["2", 1],
["12", 2],
["121", 3],
["1234", 3],
["2121", 5],
["210", 1],
["210210", 1],
["22102210", 4],
["219219", 9],
["07", 0],
["507", 0]
]
for test in tests:
res = get_combination(test[0])
if res != test[1]:
print("Error - Input: '{}' Output: {} Expected: {}".format(test[0], res, test[1]))
else:
print("OK - Input: '{}' Output: {}".format(test[0], res))
上查看它
注意测试的边界情况。您的代码未通过其中一些测试。
在撰写本文时,没有任何答案能够为输入产生正确的结果&#34; 07&#34; (应该返回0),并且kashif的答案是唯一一个只能通过该测试的答案。
以下是撰写本文时每个答案的测试结果:repl.it
答案 2 :(得分:0)
此处有dynamic programming的机会:无论以前是什么,字符串的给定后缀(因此最后N个字符)的组合数量都是固定的。
因此,您可以从字符串的结尾开始工作,并存储每个后缀的组合数。 这应该会导致运行时间大幅缩短。
$scope.choices.findIndex(function(x) {
return x.id==10;
});
答案 3 :(得分:0)
正如Trincot评论的那样,您可以通过向get_branch
函数传递偏移来节省字符串切片的时间,因此您不必通过string
或string
切片。
所以这是我的修改版本,只使用偏移量作为内部get_branch
函数的参数:
def get_combination(string):
def get_branchs(offset=0):
if len(string)-offset <= 1:
return 0
if string[offset:2+offset] <= '26':
if '0' not in string[1+offset:3+offset]:
return 1 + get_branchs(1+offset) + get_branchs(2+offset)
else:
return get_branchs(2+offset)
else:
return get_branchs(1+offset)
return 1 + get_branchs()
还有一些剩余的切片要与26进行比较并检查0
是否在子字符串中。对索引进行测试是一种替代方案,但我不确定当索引超出界限时这会如何表现(切片不介意,索引访问确实如此)
注意:我希望在回答时能够成为主题,也许codereview最适合这类问题&amp;答案。
答案 4 :(得分:0)
如果我们从字符串的末尾开始而不是从开头开始,问题可分为两部分:
可以在此处找到更多信息:Count Possible Decodings of a given Digit Sequence
以下是链接中提到的使用动态编程的C代码的Python版本:
def decodings(digits):
n_digits = len(digits)
count_table = {}
for i in range(0,n_digits+1):
count_table[i]=0
count_table[0] = 1
count_table[1] = 1
for i in range(2,n_digits+1):
#Case 1: If the last digit!=0 , repeat and add the count to the result.
if digits[i-1] > '0':
count_table[i] = count_table[i-1]
#Case 2 : If the last two digits are less than 27, repeat and the add the count to the result.
if digits[i-2] == '1' or (digits[i-2] == '2' and digits[i-1] < '7'):
count_table[i] += count_table[i-2]
return count_table[n_digits]
print decodings('121')
时间复杂度为O(n),空间复杂度为O(n)其中&#39; n&#39;是输入中的位数。