LeetCode题解:91. 解码方法,动态规划,JavaScript,详细注释

原题链接:91. 解码方法

解题思路:

创建dp数组的注意点:

  1. 根据题意,s[0]可能为'0''1',我们可以简单推导出s[0]的初始状态为:dp[1] = s[0] === '0' ? 0 : 1;
  2. 而任意一个位置dp[i]的状态,最多可能和前两个位置有关。
  3. 因此创建s.length + 1长度的dp数组,并初始化dp[0] = 1,保证可以向前查找两位的状态,也就是默认虚拟的s[-1]位置是合规的编码。
  4. dp[i]对应的字符串位置为s[i - 1]。

该题可以拆解为以下几种场景

  1. s[i - 2] + s[i - 1]的范围是10~26

    • 编码为1020,只存在一种编码方法,并且只与dp[i - 2]有关,状态转移方程:dp[i] = dp[i - 2];
    • 编码为11-1921-26,当前状态与前两个状态有关,状态转移方程:dp[i] = dp[i - 1] + dp[i - 2];
  2. s[i - 1]为0,由于1020已经处理过,此时s[i - 2] + s[i - 1]只有304050等一系列可能性,当前无法解码,可直接返回0

  3. s[i - 1]1-9,此时不会产生新的编码方法,状态转移方程:dp[i] = dp[i - 1];

/**
 * @param {string} s
 * @return {number}
 */
var numDecodings = function(s) {
  // 创建一个s.length + 1长度的数组递推,索引从1到s.length,对应s的每个位置
  // dp[i]对应的字符串位置为s[i - 1]
  let dp = new Array(s.length + 1).fill(0);
  // 由于dp[i]的状态与dp[i - 1]和dp[i - 2]有关,而我们只能创建s[0]的初始状态
  // 0位置设置为1,保证递推能有效进行。
  dp[0] = 1;
  // 创建s[0]的初始状态,为0时解码方法为0
  dp[1] = s[0] === '0' ? 0 : 1;

  // 从s[1]开始递推
  for (let i = 2; i < dp.length; i++) {
    // 临近两位的编码为10-26
    if (s[i - 2] === '1' || (s[i - 2] === '2' && s[i - 1] <= '6')) {
      // 如果当前编码为10和20,表示只能从i - 2位置编码而来,当前i - 1无解码方法
      if (s[i - 1] === '0') {
        dp[i] = dp[i - 2];
      } else {
        // 如果编码为11-19、21-26,可以由i - 1和i - 2位置编码而来
        dp[i] = dp[i - 1] + dp[i - 2];
      }
    } else if (s[i - 1] === '0') {
      // 当前编码为0,无法解码,返回0
      // 10和20的编码已经处理过,此处不会包含这两个场景
      return 0;
    } else {
      // 如果当前编码是1-9,则不会产生新的编码方法,数量与dp[i - 1]相等
      dp[i] = dp[i - 1];
    }
  }

  // 递推到数组最后位置,表示找到了解码方法数量
  return dp[s.length];
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值