算法课第10周第3题——91. Decode Ways

来源:互联网 发布:同在一起网络剧 编辑:程序博客网 时间:2024/05/16 18:36

题目描述:

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.

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.


程序代码:

class Solution {public:int numDecodings(string s) {int n = s.size();vector<int> f(n + 1, 0);// 第一位为0则无法解码,输出为0if (s[0] == '0') {return 0;}// 其余情况f[1] = 1else {f[1] = 1;}// 前两位在11~19或21~26时,f[2]=2,即前两位可以为一个十位数或两个个位数;// 第一位为0,或第二位为0且前两位不为10或20时,无法解码,输出0;// 其余情况f[2] = 1, 即需要将前两位拆成两个个位数.if ((s[0] == '1' && s[1] != '0') || s[0] == '2' && s[1] <= '6'  && s[1] > '0') {f[2] = 2;}else if ((s[0] == '0') || (s[0] != '1' && s[0] != '2' && s[1] == '0')) {return 0;}else {f[2] = 1;}// i从3开始循环,即从字符串第3位(s[2])开始循环,注意s[i-1]对应的是f[i](因为s标号比f小1)// 当第i个数和第i-1个数组成的数在11~19或21~26时,f[i] = f[i - 1] + f[i - 2];// 当两个数组成的数为10或20时,f[i] = f[i - 2];// 当个两个数组成的数不为10或20,且第i个数为0,则无法解码,直接返回结果为0// 其余情况,即组成01~09或26~99且第i个数不为0时,f[i] = f[i - 1];for (int i = 3; i <= n; i++) {if ((s[i - 2] == '1' && s[i - 1] != '0') || s[i - 2] == '2' && s[i - 1] <= '6'  && s[i - 1] > '0') {f[i] = f[i - 1] + f[i - 2];}else if ((s[i - 2] == '1' || s[i - 2] == '2') && s[i - 1] == '0') {f[i] = f[i - 2];}else if (s[i - 2] != '1' && s[i - 2] != '2' && s[i - 1] == '0') {return 0;}else {f[i] = f[i - 1];}}return f[n];}};


简要题解:

本题是一道动态规划的问题。

先理清题意。本题的输入是一串数字字符串。从1~26的数字分别解码对应A~Z的字母,需要求出这串输入的数字串共可以有几种解码方法。

令f[i]表示“前i个数字共有几种解码方法”。需要处理的初始值有f[1]和f[2]两种。对于f[1],若第一位为0则无法解码,直接输出为0;其余情况下f[1] = 1。对于f[2],若前两位在11~19或21~26时,f[2]=2,即前两位可以有2种解码方法:为一个十位数或两个个位数;若第一位为0,或第二位为0且前两位不为10或20时,无法解码,直接输出0; 其余情况下均有f[2] = 1, 即前两位只有1种解码方法:需要将前两位拆成两个个位数.

处理完初始值,接着就可以列出转移方程。枚举i = 3 ~ n,注意字符串中s[i-1]对应的是转移方程中的f[i](因为s标号比f小1)。假设已经知道了f[i-1]的值,接着可以分析如下(这部分的思考方法有点类似本周做的台阶问题):

当第i个数和第i-1个数组成的数在11~19或21~26时,f[i] = f[i - 1] + f[i - 2],即可以将第i个数和i-1个数看作两个1位数(此时对应f[i-1]的值),或是看作一个2位数(此时对应f[i-2]的值);

当两个数组成的数为10或20时,f[i] = f[i - 2],此时只能将第i和i-1个数看作是一个2位数;

当个两个数组成的数不为10或20,且第i个数为0,则无法解码,直接返回结果为0

④其余情况,即组成01~09或26~99且第i个数不为0时,f[i] = f[i - 1],此时只能将第i和i-1个数看作是两个1位数。

这样枚举完之后,就可以计算出各个f[i]的值。

最后的结果即为f[n].


本题是一道稍微复杂的动态规划问题,做本题的关键是,在列出转移方程时,有非常多种不同的情况需要分别考虑。需要仔细认真地进行分类,防止漏掉其中某种转移方程的情况。

0 0
原创粉丝点击