【Leetcode每日一题】 动态规划 - 解码方法(难度⭐)(43)

1. 题目解析

题目链接:91. 解码方法

这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。

2.算法原理

这是一道类似斐波那契数列的题目~

当我们遇到一个类似斐波那契数列的问题时,我们通常会想到使用动态规划(DP)来求解。动态规划是一种将复杂问题分解为简单子问题,并保存子问题解以便复用的算法思想。在解码字符串的问题中,我们同样可以采用这种方法。

1. 状态定义

首先,我们需要明确问题的状态。在这里,我们定义dp[i]为字符串中从第0个字符到第i个字符这一段区间上,所有可能的解码方法的数量。这样,当我们求出dp[n](其中n是字符串的长度)时,就得到了整个字符串的解码方法数。

2. 状态转移

接下来,我们要分析dp[i]是如何从前面的状态转移过来的。考虑到第i个字符,我们有两种可能的解码方式:

  • 单独解码第i个字符:当第i个字符是'1'到'9'之间的数字时,它可以单独解码成一个字母。此时,字符串从第0个字符到第i个字符的解码方法数就等于从第0个字符到第i-1个字符的解码方法数,因为我们可以将前面所有的解码方法都加上这个单独的字符。即dp[i] += dp[i-1]
  • 与前一个字符结合解码:如果第i-1个字符和第i个字符组合起来在'10'到'26'之间(表示一个有效的两位数字),那么它们可以合并解码成一个字母。此时,字符串从第0个字符到第i个字符的解码方法数就等于从第0个字符到第i-2个字符的解码方法数,因为我们可以将前面所有的解码方法都加上这个两位数字。即dp[i] += dp[i-2]

需要注意的是,如果第i个字符是'0',那么它不能单独解码成一个字母,必须与前一个字符结合。如果结合后的数字不在'10'到'26'之间,那么这段字符串就无法解码,此时dp[i]应该保持为0。

3. 初始化

在开始计算之前,我们需要对dp数组进行初始化。由于我们的状态转移依赖于dp[i-1]dp[i-2],所以至少需要初始化前两个位置的值。

  • 对于dp[0]:如果字符串的第一个字符是'0',那么整个字符串无法解码,dp[0]应该为0;否则,至少有一种解码方法(即单独解码第一个字符),dp[0]应该为1。
  • 对于dp[1]:我们需要考虑第一个和第二个字符的组合。如果第二个字符是'1'到'9',那么它可以单独解码,此时dp[1]应该加上dp[0];如果第一个字符和第二个字符组合起来是一个有效的两位数字,那么也应该有一种解码方法,此时dp[1]应该再加1。

3.代码编写

class Solution 
{
public:
    int numDecodings(string s) 
    {
        int n = s.size();
        vector<int> dp(n);

        dp[0] = s[0] != '0';
        if(n == 1) return dp[0];

        if(s[0] != '0' && s[1] != '0') dp[1]++;
        int t = (s[0] - '0') * 10 + (s[1] - '0');
        if(t >= 10 && t <= 26) dp[1]++;

        for(int i = 2; i < n; i++)
        {
            if(s[i] != '0') dp[i] += dp[i - 1];
            int m = (s[i - 1] - '0') * 10 + (s[i] - '0');
            if(m >= 10 && m <= 26) dp[i] += dp[i - 2];
        }
        return dp[n - 1];
    }
};

The Last

嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。

觉得有点收获的话,不妨给我点个吧!

如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~ 

  • 18
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天进步亿丢丢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值