LeetCode(91):解碼方法


Medium!

題目描述:

一條包含字母 A-Z 的消息通過以下方式進行了編碼:

'A' -> 1
'B' -> 2
...
'Z' -> 26

給定一個只包含數字的非空字符串,請計算解碼方法的總數。

示例 1:

輸入: "12"
輸出: 2
解釋: 它可以解碼為 "AB"(1 2)或者 "L"(12)。

示例 2:

輸入: "226"
輸出: 3
解釋: 它可以解碼為 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。

解題思路:

這道題要求解碼方法,跟之前那道 Climbing Stairs 爬梯子問題 非常的相似,但是還有一些其他的限制條件,比如說一位數時不能為0,兩位數不能大於26,其十位上的數也不能為0,出去這些限制條件,根爬梯子基本沒啥區別,也勉強算特殊的斐波那契數列,當然需要用動態規划Dynamic Programming來解。

建立一位dp數組,長度比輸入數組長度多2,全部初始化為1,因為斐波那契數列的前兩項也為1,然后從第三個數開始更新,對應數組的第一個數。對每個數組首先判斷其是否為0,若是將改為dp賦0,若不是,賦上一個dp值,此時相當如加上了dp[i - 1], 然后看數組前一位是否存在,如果存在且滿足前一位不是0,且和當前為一起組成的兩位數不大於26,則當前dp值加上dp[i - 2], 至此可以看出來跟斐波那契數組的遞推式一樣。

C++解法一:

 1 class Solution {
 2 public:
 3     int numDecodings(string s) {
 4         if (s.empty() || (s.size() > 1 && s[0] == '0')) return 0;
 5         vector<int> dp(s.size() + 1, 0);
 6         dp[0] = 1;
 7         for (int i = 1; i < dp.size(); ++i) {
 8             dp[i] = (s[i - 1] == '0') ? 0 : dp[i - 1];
 9             if (i > 1 && (s[i - 2] == '1' || (s[i - 2] == '2' && s[i - 1] <= '6'))) {
10                 dp[i] += dp[i - 2];
11             }
12         }
13         return dp.back();
14     }
15 };

下面這種方法跟上面的方法的思路一樣,只是寫法略有不同:

C++解法二:

 1 class Solution {
 2 public:
 3     int numDecodings(string s) {
 4         if (s.empty()) return 0;
 5         vector<int> dp(s.size() + 1, 0);
 6         dp[0] = 1;
 7         for (int i = 1; i < dp.size(); ++i) {
 8             if (s[i - 1] != '0') dp[i] += dp[i - 1];
 9             if (i >= 2 && s.substr(i - 2, 2) <= "26" && s.substr(i - 2, 2) >= "10") {
10                 dp[i] += dp[i - 2];
11             }
12         }
13         return dp.back();
14     }
15 };

我們再來看一種空間復雜度為O(1)的解法,我們用兩個變量c1, c2來分別表示s[i-1]和s[i-2]的解碼方法,然后我們從i=1開始遍歷,也就是字符串的第二個字符,我們判斷如果當前字符為'0',說明當前字符不能單獨拆分出來,只能和前一個字符一起,我們先將c1賦為0,然后我們看前面的字符,如果前面的字符是1或者2時,我們就可以更新c1 = c1 + c2,然后c2 = c1 - c2,其實c2賦值為之前的c1,如果不滿足這些條件的話,那么c2 = c1。

C++解法三:

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM