【动态规划】LeetCode 91 解码方法-Medium

397 阅读2分钟

题目

一条包含字母 A-Z 的消息通过以下方式进行了编码:

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

给定一个只包含数字的非空字符串,请计算解码方法的总数。

题目数据保证答案肯定是一个 32 位的整数。

示例 1:

输入:s = "12"
输出:2
解释:它可以解码为 "AB"1 2)或者 "L"12)。

示例 2:

输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。

动态规划四步走

1. 定义状态
2. 初始状态
3. 状态转移方程
4. 从dp[]中获取结果

具体到题目

定义状态

定义dp 数组,第 i 个元素表示从第一个字符到第i个字符的解码数。

初始状态

若输入不为空,且第一个字符不为0,则dp[i]=1,否则直接返回0

状态转移方程

if s[i] === 0 => s[i-1]1或者2,则dp[i]=dp[i - 2]
else 
   if s[i - 1] === '0' => dp[i] = dp[i - 1]
   else  判断s[i-1]与s[i]组成的数字是否小于等于26,若是则dp[i] =dp[i - 1]+dp[i - 2],否则dp[i] = dp[i - 1]

完整代码

/**
 * @param {string} s
 * @return {number}
 */
var numDecodings = function (s) {
  // dp[i]表示第i个字符的所有可能
  const list = s.split('');
  if (list.length === 0 || list[0] === '0') {
    return 0;
  }
  const dp = [];
  dp[0] = 1;
  for (let i = 1; i < list.length; i++) {
    const curChar = list[i];
    if (curChar === '0') {
      if (['1', '2'].includes(list[i - 1])) {
        dp[i] = i >= 2 ? dp[i - 2] : 1;
      } else {
        return 0;
      }
    } else {
      if (list[i - 1] === '0') {
        dp[i] = dp[i - 1];
      } else {
        const number = Number(list[i - 1]) * 10 + Number(list[i]);
        if (number <= 26) {
          dp[i] = i >= 2 ? dp[i - 1] + dp[i - 2] : 2;
        } else {
          dp[i] = dp[i - 1];
        }
      }
    }
  }
  console.log(dp);
  return dp.pop();

总结

第一次思路清晰的做对了动态规划的题目,需要做的是冷静思考,慢慢分析,得到状态转移方程。