题目来源

题目描述

在这里插入图片描述

在这里插入图片描述

class Solution {
public:
    int numDecodings(string s) {

    }
};

题目分析

题意分析

我们先来理解一下题目的解码规则
在这里插入图片描述

如例子s = “226”,可以分为两种情况:

  • 将每一个数字单独编码,因此可以解码成"BBF"(2 2 6)
  • 将相邻两位数字组合起来解码(组合的数字范围在10 ~ 26之间),因此可以解码成"BZ"(2 26), "VF"(22 6)

两种情况是或的关系,互不影响,将其相加,那么226共有3种不同的解码方式

不难发现,对于字符串s的某个位置而言,我们只关心[位置i自己能否形成独立的item和[位置i能够与上一位置(i - 1)能否形成item]

典型的划分型动态规划

这道题要求解码方法,除去一些限制条件(比如说一位数时不能为0,两位数不能大于 26,其十位上的数也不能为0),跟爬梯子基本没啥区别,也勉强算特殊的斐波那契数列

  • 定义dp:dp[i] 表示s中前i个字符组成的子串的解码方法的个数,长度比输入数组长多多1,并将 dp[0] 初始化为1。

实现:

class Solution {
public:
    int numDecodings(string s) {
        if (s.empty() || s[0] == '0') return 0;
        vector<int> dp(s.size() + 1, 0);
        dp[0] = 1;
        for (int i = 1; i < dp.size(); ++i) {
            if (s[i - 1] != '0') dp[i] += dp[i - 1];
            if (i >= 2 && s.substr(i - 2, 2) <= "26" && s.substr(i - 2, 2) >= "10") {
                dp[i] += dp[i - 2];
            }
        }
        return dp.back();
    }
};

实现:

class Solution {
public:
    int numDecodings(string s) {
        if (s.empty() || s[0] == '0') return 0;
        vector<int> dp(s.size() + 1, 0);
        dp[0] = 1;
        for (int i = 1; i < dp.size(); ++i) {
            dp[i] = (s[i - 1] == '0') ? 0 : dp[i - 1];
            if (i > 1 && (s[i - 2] == '1' || (s[i - 2] == '2' && s[i - 1] <= '6'))) {
                dp[i] += dp[i - 2];
            }
        }
        return dp.back();
    }
};

类似题目

题目
leetcode:91. 解码方法Decode Ways
leetcode:639. *可以匹配多个字符时,有多少解码方法 II Decode Ways II
leetcode:70. 爬楼梯 Climbing Stairs 动态规划

更多推荐