zoukankan      html  css  js  c++  java
  • 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 };
  • 相关阅读:
    多个在线参考手册,值得收藏
    DIV层,点“+”展开,“-”关闭
    网页设计标准尺寸
    【转】 大年三十整理的asp.net资料! (.NET) (ASP.NET)
    【转】xml操作
    【配色】web2.0 配色参考
    【转】关闭开机硬盘自检的方法
    【转】css的一些基础的东西
    web.config加密解密
    [转]用 Javascript 获取滚动条位置等信息
  • 原文地址:https://www.cnblogs.com/ariel-dreamland/p/9159520.html
Copyright © 2011-2022 走看看