计算编码的递归关系

时间:2018-02-20 01:50:57

标签: recursion dynamic-programming recurrence

我最近偶然发现了一个很好的问题,即使在很长一段时间后似乎无法找出复发关系。

以下是问题陈述:

A message containing letters from A-Z is being encoded to numbers using 
the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.

例如:

if the given input is 121 we can have three encodings
1. ABA (1-->A, 2-->B)
2. LA  (12 -->L, 1-->A)
3. AU  (1--A, 21--U)
All I was able to achieve was the base cases:
if len(S) == 1:
    if S == "0":
       return 0
    return 1
if len(S) == 2:
   if int(S) > 26:
       return 1
   return 2

除了基本情况,我似乎无法弄清复发关系。任何帮助将不胜感激。感谢。

2 个答案:

答案 0 :(得分:0)

假设我们当前位于数字i数组中的索引a[n]。右边的位数(包括当前位数)为n - i。以下是我们需要检查的案例:

  • 如果n - i <= 0然后返回1(因为只有一种方法可以排列零位数)。
  • 如果n - i > 1
    • 如果a[i]a[i + 1]给出[10, 26]范围内的数字,请添加从i + 2开始的组合数(即我们使用这两位数字)。
  • 然后必须有n - i = 1或两个超出范围的数字,因此请添加从i + 1开始的组合数(即消耗一位数)。

伪代码:

def countCombos(a[n], i):
   if i >= n: return 1
   two <- 0
   if n - i > 1:
      if a[i] == 1 || (a[i] == 2 && a[i + 1] <= 6):
         two <- countCombos(a, i + 2)
   return two + countCombos(a, i + 1) 

我会留给你实施备忘录。

答案 1 :(得分:0)

暂时假设s不包含零;如果是,f(s)=0

只有一种方法可以解码长度为1的字符串:f(s)=1 |s|=1。对于空字符串---即长度为零的字符串---我们设置f(s)=0

现在,为了重复,我们从左端开始,如果s[1..2] <= 26我们有两种解释方式:decode(s[1]), decode(s[2])decode(s[1..2])。否则,如果s[1..2]>26只有一个选择。

这自然导致以下复发: count(s) if |s| <= 1 then return |s| else v = 0 if s[1..2] <= 26: v = f(s[1:]) return v + f(s[2:])

显然你想在实践中做一些记忆,以避免指数运行时间。

作为旁注,请注意当s具有任何1<=i<|s| s[i..i+1] <= 26的属性时,重现恰好是斐波那契重复(稍微移位)。