所以我试图制作一个程序,打印出消息解码的方式。 可以在代码本身中轻松理解映射。现在它适用于大多数数字,但对于某些人来说,它并没有正确计算。例如数字1111,它解决它就像有两种方法解码它,但实际上有4种不同的方法。
这是我的代码:
mapping=["1", "2", "3", "4", "5", "6", "7" "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"]
encodedCases = ["918", "739", "1142", "56", "82", "118", "1219", "6", "862", "1111"]
def decodeNumber(test, mapping):
count=0
checkFirstLast=0
for i in range(9, len(mapping)):
if mapping[i] in test:
count+=1
if test[:2]!=test[-2:]:
if len(test)>3 and mapping[i] in test[:2]:
checkFirstLast+=1
elif len(test)>3 and mapping[i] in test[-2:]:
checkFirstLast+=1
if checkFirstLast==2:
count+=1
print count + 1
for test in encodedCases:
test = test.strip()
decodeNumber(test, mapping)
使用此方法我还没有找到一种方法可以正确地成功计算它。有没有更好的方法来实现这一目标?提前谢谢!
注意 - 映射是字母表的表示,为每个字母赋予其在字母表中的位置值。
答案 0 :(得分:2)
我可以想到一种递归方法:
def decodeNumber(test):
if not test: # check if test is empty
return 1
count = 0
for i in mapping:
if test.startswith(i):
count += decodeNumber(test[len(i):])
return count
for test in encodedCases:
test = test.strip()
print test, "==>" , decodeNumber(test)
decodeNumer
检查test
输入是否以映射中的条目开头。对于它所做的所有条目,它自己调用。新参数为test[len(i):]
,表示test
,条目从开头删除。
例如,让test = "918"
:当i == "9"
和新参数test[len("9"):]
等于" 18"时,if语句首次评估为真。
总计数计算为消耗完整输入的路径总数。
答案 1 :(得分:1)
这是一个干净的动态编程方法,它在最坏情况下运行时间O(nk),其中k是映射的长度,n是字符串的长度。特别是,与天真的递归方法不同,它不会在输入上采用指数时间。
这适用于Python 3.2 +。
import functools
@functools.lru_cache(None) # lru_cache implements memoization
def decodeNumber(s, mapping):
if not s:
return 1 # base case: there's one way to decode the empty string
# iterate over all possible prefixes, and count the ways to decode the resulting suffixes
res = 0
for m in mapping:
if s.startswith(m):
res += decodeNumber(s[len(m):], mapping)
return res
请注意,mapping
在此实现中应该是tuple
(您也可以省略函数声明中的mapping
参数以使用全局mapping
变量。
Memoization使我们不必重复计算相同的值。如果没有memoization,算法必须至少执行res
个递归调用(因为每个计算的解码必须以最终的return 1
情况递归调用结束)。通过memoization,我们可以跳过已经处理过的递归调用。
如果您尝试使用和不使用memoization运行decodeNumber("1" * 256, ("1", "11"))
,则可以看到差异。没有记忆就永远不会完成。通过记忆,结果是即时的。
答案 2 :(得分:0)
这是一个O(n)时间复杂度(一次通过)和O(1)空间复杂度的迭代解决方案:
def ways(s):
if (len(s)==0 or len(s)==1): return 1
if (int(s[0:2])<27): prev = 2
else: prev = 1
prevprev = 1
for i in range(2,len(s)):
if (int(s[i-1:i+1])<27): curr = prev + prevprev
else: curr = prev
prevprev = prev
prev = curr
return prev
这是一种动态编程方法。在每次迭代中,添加另一个数字并计算直至该数字为止的消息解码方式。如果前面的数字和当前的数字大于26,则当前的数字与前面的数字相同,因为当前的数字必须是自己的数字。否则,对消息进行编码的方式等于不对消息进行编码的方式(不带前两者),再对不对消息进行编码的方式(对上)。
还有1111(1-1-1-1、1-1-11、1-11-1、11-1-1、11-11)的5种解码方式