[LeetCode 91] 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.

Example

Given encoded message 12, it could be decoded as AB (1 2) or L (12).
The number of ways decoding 12 is 2.

 

Solution 1. DFS Recursive Solution

From the given mapping, we know that the decoding must be done in the following way.

1. single character decode: must not be '0', can be from '1' to '9'

2. two characters decode: must be from '10' to '26'

We can derive a recursive formula that solves this problem.

f(i) = f(i - 1) + f(i - 2) if s[i] is not '0' and s[i - 1, i] is between 10 and 26;

f(i) = f(i - 1) if s[i] is not '0' but s[i - 1, i] is outside of [10, 26];

f(i) = f(i - 2) if s[i] is '0' but s[i - 1, i] is between 10 and 26;

f(i) = 0 if s[i] is '0' and s[i - 1, i] is outside of [10, 26];

 

We can easily write the following dfs recursive solution.  But it is very inefficient as we repeatedly 

calculate the same subproblems, just like the problems Climbing Stairs and Fibonacci. The only 

difference between this problem and climbing stairs is that this problem requires a condition check

when computing subproblems, since not every one or two characters divide meet thedecode mapping

requirement.

 

 1 public class Solution {
 2     public int numDecodings(String s) {
 3         if(s == null || s.length() == 0){
 4             return 0;
 5         }
 6         return dfs(s, s.length() - 1);   
 7     }
 8     private int dfs(String s, int end){
 9         //base case of length 1
10         if(end == 0){
11             if(s.charAt(end) != '0'){
12                 return 1;
13             }
14             else{
15                 return 0;
16             }
17         }
18         //base case of length 2
19         if(end == 1){
20             int ways = 0;
21             if(s.charAt(end - 1) == '0'){
22                 return 0;
23             }
24             if(s.charAt(end) != '0'){
25                 ways++;
26             }
27             int num = (s.charAt(end - 1) - '0') * 10 + (s.charAt(end) - '0');
28             if(num <= 26){
29                 ways++;
30             }
31             return ways;
32         }
33         int ways = 0;
34         if(s.charAt(end) != '0'){
35             ways += dfs(s, end - 1);
36         }
37         int num = (s.charAt(end - 1) - '0') * 10 + (s.charAt(end) - '0');
38         if(s.charAt(end - 1) != '0' && num <= 26){
39             ways += dfs(s, end - 2);
40         }
41         return ways;
42     }
43 }

 

 Solution 2. Dynamic Programming 

To avoid overlapping subproblems computation, we use dynamic programming.

State:

states[i]: the total number of ways to decode the first i characters

Function:

states[i] += states[i - 1] if s[i - 1] != '0';

states[i] += states[i - 2] if s[i - 2, i - 1] is between 10 and 26;

if states[i] == 0 after the above two calculation, return 0 as it is impossible to decode

the input string according to the given mapping rule.

Initialization:

states[0] = 1; when there is no character, no decoding is needed, so we have 1 way of decoding it, which is do nothing.

states[1] = (s.charAt(0) == '0' ? 0 : 1);

states[i] = 0 for i >= 2; 

Answer:

states[s.length]; if any states[i] for i != 0 is 0 after calculation, we can simply return 0 as 

it is impossible to decode. 

 

 1 public class Solution {
 2     public int numDecodings(String s) {
 3         if(s == null || s.length() == 0){
 4             return 0;
 5         }
 6         int n = s.length();
 7         int[] states = new int[n + 1];
 8         states[0] = 1;
 9         states[1] = (s.charAt(0) == '0' ? 0 : 1);
10         if(states[1] == 0){
11             return 0;
12         }
13         for(int i = 2; i <= n; i++){
14             states[i] = 0;
15         }
16         for(int i = 2; i <= n; i++){
17             int num = (s.charAt(i - 2) - '0') * 10 + (s.charAt(i - 1) - '0');
18             if(s.charAt(i - 1) != '0'){
19                 states[i] += states[i - 1];
20             }
21             if(s.charAt(i - 2) != '0' && num <= 26){
22                 states[i] += states[i - 2];
23             }
24             if(states[i] == 0){
25                 return 0;
26             }
27         }
28         return states[n];
29     }
30 }
 

Related Problems

Climbing Stairs

Climbing Stairs II 

Wildcard Matching

Regular Expression Matching

Find the Missing Number II

posted @ 2017-06-01 11:58  Review->Improve  阅读(376)  评论(0编辑  收藏  举报