1. 程式人生 > >動態規劃中級教程91. Decode Ways

動態規劃中級教程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.

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.

題目大意: 給我們一個字串只包含數字0-9,告訴我們’a’-‘z’對應數字的’1’-“26”
問我們一共可以得到多少不同的解碼方式

問題是多少種不同,很容易想到動態規劃

先定義動態規劃狀態 dp[i]代表[0,i]可以組成多少種不同的編碼方式

接著定義初時狀態
dp[0] = 1 (‘1’-‘9’)
dp[0] = 0 (‘0’)
上面的初時狀態代表 ‘1’-‘9’那麼一種否則0種

接著我們填寫dp[1]
如果[0,1]構成的兩個字元大小在(10-26)之間代表本身是一種解碼方式
dp[1]++;

如果[1]是合法的那麼
dp[1] = 1+dp[0];

接著我們可以分析後面的狀態並且寫出狀態轉移方程

dp[i] = (如果本身著一位可以編碼並且和前一位的和可以編碼)dp[i-1]+dp[i-2].

dp[i] = ( 如果本身可以編碼但是前一位不可以編碼) dp[i-1].

dp[i] = (如果本身不可以編碼但是前一位和可以編碼) dp[i-2].

狀態轉移寫完後可以寫出相應的程式如下

class Solution {
public:
    bool islegal( string s ){
        int num = 0 ;
        for( int i=0 ; i<s.size() ; i++){
            num = num * 10
+ s[i] -'0'; } if( num >=10 && num <= 26) { return true ;} return false; } int numDecodings(string s) { if( s.size() == 0 ){ return 0 ;} if( s.size() == 1 ){ return (s[0]!='0') ; } int dp[s.size()]; memset( dp , 0 , sizeof( dp ) ) ; if(s[0]!='0' ){ dp[0] = 1 ; } else{ dp[0] = 0 ; } if( islegal( s.substr( 0 , 2 ) ) ) { if( s[1] =='0'){ dp[1] = 1 ; } else{ dp[1] = 2; } } else{ if( s[1] == '0' ){ dp[1] = 0 ; } else { dp[1] = dp[0] ;} } for( int i = 2 ; i< s.size() ; i++ ){ if( s[i] != '0' ){ if( islegal( s.substr( i-1 , 2 ) ) ){ dp[i] = dp[i-1] + dp[i-2]; } else{ dp[i] = dp[i-1] ; } } else{ if( islegal( s.substr( i-1 , 2 ) ) ){ dp[i] = dp[i-2]; } else{ dp[i] = 0 ; } } } return dp[s.size()-1] ; } };

時間複雜度分析

O(n)

空間複雜度分析

O(n)