A message containing letters from A-Z
is being encoded to numbers using the following mapping:git
'A' -> 1 'B' -> 2 ... 'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.app
For example,
Given encoded message "12"
, it could be decoded as "AB"
(1 2) or "L"
(12).post
The number of ways decoding "12"
is 2.spa
這道題一開始想用backtracking構造出全部可能的decoding ways,而後統計個數,可是後來發現這樣的解法不管是空間複雜度仍是時間複雜度以及實現的難度都不太理想,必定還有更好的解決辦法,沒錯,那就是動態規劃了。翻譯
咱們能夠構造一個用於dp的vector,大小爲輸入string長度+1。其中第[0]個元素值爲1,視爲邊界值,而後剩下的部分能夠和輸入string的每一個字符都一一對應起來,其含義就是到該處時有多少種decoding方法。可想而知,第一個字符只要不是'0',就必定能夠翻譯,所以dp[1] = 1。code
那麼如何構造狀態轉移方程呢?假設咱們處理到了s[i]的位置,那麼首先單個s[i]的字符是能夠翻譯的,若是隻翻譯單個s[i],那麼翻譯的種類有dp[i]種。若s[i-1]與s[i]構成的字符串其值是小於等於26的,那麼還能夠再有dp[i-1]種翻譯方法。總共dp[i]+dp[i-1]種(即到s[i-2]處有多少種翻譯方法,結合上s[i-1,i];以及到s[i-1]有多少種翻譯方法,結合上s[i])。blog
若是s[i-1]與s[i]構成的字符串其值大於26,那麼顯然就只能和s[i-1]處的翻譯方法數量同樣了。字符串
另外還有一個特殊狀況,即s[i]=0,由於單個0是沒有辦法翻譯的,也就是說此時若是按照dp[i]的翻譯方式(翻譯到s[i-1],以後的字符串將以0打頭)是不可行的,因此要將dp[i]賦值成0。string
最後,實際上每次在進行狀態轉移時,咱們最多隻須要獲取前兩個狀態,所以這裏的空間複雜度還能夠進一步從O(n)縮小到O(1),這裏就不進一步展開了。上代碼:it
class Solution { public: int numDecodings(string s) { int size = s.length(); if (size <= 0 || s[0] == '0') { return 0; } vector<int> dp(size + 1, 0); dp[0] = dp[1] = 1; for (int i = 1; i < size; ++i) { if (s[i] == '0') { dp[i] = 0; } if (s[i - 1] == '1' || s[i - 1] <= '2' && s[i] <= '6') { dp[i + 1] = dp[i] + dp[i - 1]; } else { dp[i + 1] = dp[i]; } } return dp[size]; } };