Decode Ways
A message containing letters fromA-Zis 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.
For example,
Given encoded message"12", it could be decoded as"AB"(1
2) or"L"(12).
The number of ways decoding"12"is 2.
转弯过来了:两个条件判断的时候就使用两个动态规划表来存储数据,因为每次交叉判断.
当然leetcode论坛有使用一个表的,不过使用一个表就很不好理解。
记住:有多少个条件判断就需要使用多少个表来存储数据,因为每个判断条件要改动的数据结果都不一样,不能混饶了,保持思路清晰。注意:一定需要画递归树,一步一步地区填表,才不会乱,否则很容易出错!
int numDecodings(string s)
{
if (s.length()<1 || s[0] == '0') return 0;
if (s.length() == 1) return 1;
vector<int> ta1(s.length());
vector<int> ta2(s.length());
ta1[0] = 1; ta2[0] = 0;
if (s[1] != '0') ta1[1] = 1;
if (s[0] == '1' || s[0]=='2'&&s[1]<='6') ta2[1]=1;
else ta2[1]=0;
for (int i = 2; i < s.length(); i++)
{
if (s[i]!='0') ta1[i]=ta1[i-1]+ta2[i-1];
else ta1[i]=0;
if (s[i-1]=='1' || s[i-1] =='2' && s[i] <= '6')
ta2[i] = ta1[i-2]+ta2[i-2];
else ta2[i] = 0;
}
return ta1[s.length()-1]+ta2[s.length()-1];
}
6个变量2个一维表,存储数据的动态规划法:
int numDecodings2(string s)
{
if (s.length()<1 || s[0] == '0') return 0;
if (s.length() == 1) return 1;
vector<int> ta1(3);
vector<int> ta2(3);
ta1[0] = 1; ta2[0] = 0;
if (s[1] != '0') ta1[1] = 1;
if (s[0] == '1' || s[0]=='2'&&s[1]<='6') ta2[1]=1;
else ta2[1]=0;
for (int i = 2; i < s.length(); i++)
{
if (s[i]!='0') ta1[i%3]=ta1[(i-1)%3]+ta2[(i-1)%3];
else ta1[i%3]=0;
if (s[i-1]=='1' || s[i-1] =='2' && s[i] <= '6')
ta2[i%3] = ta1[(i-2)%3]+ta2[(i-2)%3];
else ta2[i%3] = 0;
}
return ta1[(s.length()-1)%3]+ta2[(s.length()-1)%3];
}
也是使用6个变量就可以了:
int numDecodings3(string s)
{
if (s.length()<1 || s[0] == '0') return 0;
if (s.length() == 1) return 1;
int a=0,b=0,c=0;
int d=0,e=0,f=0;
a = 1; d = 0;
if (s[1] != '0') b = 1;
if (s[0] == '1' || s[0]=='2'&&s[1]<='6') e=1;
else e=0;
for (int i = 2; i < s.length(); i++)
{
c=b;
if (s[i]!='0') b=b+e;
else b=0;
f=e;
if (s[i-1]=='1' || s[i-1] =='2' && s[i] <= '6')
e = a+d;
else e = 0;
a=c; d=f;
}
return b+e;
}
高级境界,已经是绕过递归思维,直接填表就行了。
至于是怎么做到的?
前提应该是:
1 递归法很熟了
2 动态规划法很熟了
简单描述下面程序的思维:
当前编码方法可以是两种:
1 当前字母编码编码为一个字母
2 当前字母和前一个字母编码为两个字母
判断两者是否合法。
//2014-2-14 update
int numDecodings(string s)
{
if (s.empty() || s[0] == '0') return 0;
int *A = new int[s.length()+1];
A[0] = 1, A[1] = 1;
for (int i = 1; i < s.length(); i++)
{
A[i+1] = (s[i]=='0')? 0:A[i];
if (s[i-1]=='1' || s[i-1]=='2'&&s[i]<'7') A[i+1] += A[i-1];
}
return A[s.length()];
}
最高境界,三个变量:
//2014-2-14 update
int numDecodings(string s)
{
if (s.empty() || s[0] == '0') return 0;
int a = 1, b = 1, c = 1;
for (int i = 1; i < s.length(); i++)
{
c = (s[i]=='0')? 0:b;
if (s[i-1]=='1' || s[i-1]=='2'&&s[i]<'7') c += a;
a = b, b = c;
}
return c;
}
解码方式的动态规划算法
本文详细介绍了如何使用动态规划解决解码问题,并通过多种方法优化算法效率,包括使用多个一维表存储数据和减少变量数量。文章还提供了解码问题的高级境界,即直接填表的方法,同时给出了具体的代码实现。
208

被折叠的 条评论
为什么被折叠?



