【Leetcode】【Medium】Decode Ways

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.

 

解题思路:

使用动态规划的思想。

(一)

初始想法可以建立一个数组,数组的每一位保存对应字符串的每一位可能出现的解码方式,例如:

字符串321321312;其对应的截止到每一位可能存在的解码方式种类为:

3 - 1种

32 - 1种

321 - 2种

3213 - 3种

32132 - 5种

....

所以得到解码方式数组为:

原字符串S:    3  2  1  3  2  1  3  1  2

解码种类数组A:  1  1  2  3  5  8 16 16 32

发现:

(1)如果当前字符可以和上一个字符组成二元字符,例如'1'和'2'组成'12',那么A[i] = A[i-1] + A[i-2];

  很好理解,等于将'1' '2'分开的解码种类与将'12'合起来的解码种类之和;

(2)如果当前字符不能和上一个字符组成二元字符,那么A[i] = A[i-1];

 

(二)

因此,进一步的思路是,不需要建立一个数组,只需要保存i-2和i-1的解码种类数就可以了,分别用r1和r2表示;

如果当前字符可以组成二元字符,那么当前字符的次数 = r1 + r2;

如果不能,当前字符次数 = r1;

 

(三)

进一步发现,只用r1和r2两个变量就够了

(1)每次遇到可以组成二元字符的字符时,就更新r1,使r2等于旧的r1:

  r1= r1 + r2;

  r2 = r1;

(2)当不能组成二元字符时,r1不变,更新r2为r1;

(3)最终返回r1;

 

注意:

如果当前字符是'0',如果将'0'单独算,则不能产生任何解码数,即解码数为0;

 

代码:

 1 int numDecodings(string s) {
 2     if (!s.size() || s.front() == '0') return 0;
 3     int r1 = 1, r2 = 1;
 4 
 5     for (int i = 1; i < s.size(); i++) {
 6         if (s[i] == '0') r1 = 0;
 7 
 8         if (s[i - 1] == '1' || s[i - 1] == '2' && s[i] <= '6') {
 9             r1 = r2 + r1;
10             r2 = r1 - r2;
11         } else {
12             r2 = r1;
13         }
14     }
15 
16     return r1;
17 }

 

posted @ 2015-09-01 17:15  胡潇  阅读(570)  评论(0编辑  收藏  举报